Yii2 multiple forms in a single action

forms, yii2

Solution

Id in `ActiveForm` does't mean id in $_POST. You should use:

`$membersBans->load(Yii::$app->request->post())`

or

`$membersBans->load(Yii::$app->request->post('MembersBans'))`

for load attributes from form.

For example multiple forms from CeBe (http://www.yiiframework.com/forum/index.php/topic/53935-solved-subforms/page__p__248184#entry248184)

public function actionCreate()
{   
    $user = new User;
    $profile = new Profile;

    if ($user->load(Yii::$app->request->post()) && $profile->load(Yii::$app->request->post()) && Model::validateMultiple([$user, $profile])) {

        $user->save(false); // skip validation as model is already validated
        $profile->user_id = $user->id; // no need for validation rule on user_id as you set it yourself
        $profile-save(false); 

        return $this->redirect(['view', 'id' => $user->id]);
    } else {
        return $this->render('create', [
            'user' => $user,
            'profile' => $profile,
        ]);
    }
}

In your `action` you use one `model`. I think you should extends `MembersBans` to `MembersBansIp` class. And your `action`:

public function actionList() {
    $membersBans = new MembersBans();
    $membersBansIp = new MembersBansIp();
    if ($membersBans->load(Yii::$app->request->post())) {
        $membersBans->banMember();
    }
    if ($membersBansIp->load(Yii::$app->request->post())) {
        $membersBansIp->banIp();
    }
    return $this->render('list', [
                'membersBans' => $membersBans,
                'membersBansIp' => $membersBansIp,
    ]);
}

In `view`:

<?php
    $activeForm = ActiveForm::begin([
            'id' => 'banMember',
])
?>

    <?= $activeForm->field($membersBans, 'fieldMembersBans') ?>
    <?= Html::submitButton('Login', ['class' => 'btn btn-primary']) ?>
    <?php ActiveForm::end() ?>
<?php
    $activeForm = ActiveForm::begin([
            'id' => 'banMemberIp',
])
?>

    <?= $activeForm->field($membersBansIp, 'usernameMembersBansIp') ?>
    <?= Html::submitButton('Login', ['class' => 'btn btn-primary']) ?>
    <?php ActiveForm::end() ?>

EDIT

I put your code. He is work. https://yadi.sk/i/y7PkwGUPekjPD https://yadi.sk/i/h8dCYQz3ekk2B

But I change controller to this

$membersBans = new MembersBans();
        if ($membersBans->load(Yii::$app->request->post())) {
            $membersBans->banMember();
        }
        if ($membersBans->load(Yii::$app->request->post())) {
            $membersBans->banIp();
        }

And in `model` change `Members` to `User`, because I have not `Members` objects:

$memberInfo = User::findByUsername($this->username);
        if ($memberInfo) {
            $this->ban_memberid = $memberInfo->id;

Resume: your code is worked. Change `controller`, how I written up.

Problem

Which is the right way to handle multiple forms in a single action? Here is my models/MembersBans.php ``` <?php namespace app\models; use Yii; use yii\behaviors\TimestampBehavior; use app\models\Members; class MembersBans extends \yii\db\ActiveRecord { public $username; public static function tableName() { return '{{%members_bans}}'; } public static function primaryKey() { return array('ban_id'); } public function behaviors() { return [ [ 'class' => TimestampBehavior::className(), 'createdAtAttribute' => 'date_added', 'updatedAtAttribute' => 'last_updated', ], ]; } public function rules() { return [ [['ban_id', 'ban_memberid', 'date_added', 'last_updated'], 'integer'], [['username', 'end_date'], 'safe'], ['end_date', 'date', 'format' => 'yyyy-mm-dd'], [['ban_ip'], 'string', 'max' => 40], [['reason'], 'string', 'max' => 255] ]; } public function attributeLabels() { return [ 'ban_id' => Yii::t('app', 'ID на бана'), 'ban_memberid' => Yii::t('app', 'Потребителско ID'), 'username' => 'Потребителско име', 'ban_ip' => Yii::t('app', 'IP адрес'), 'end_date' => Yii::t('app', 'Дата на изтичане'), 'reason' => Yii::t('app', 'Причина за бана'), 'date_added' => Yii::t('app', 'Дата на добавяне'), ]; } public function getMemberBans() { $bans = $this->find()->where('ban_memberid'); return $bans; } public function getIpBans() { $bans = $this->find()->where('ban_ip'); return $bans; } public function getMember() { return $this->hasOne(Members::className(), ['member_id' => 'ban_memberid']); } public function banMember() { $memberInfo = Members::findByUsername($this->username); if ($memberInfo) { $this->ban_memberid = $memberInfo->member_id; if ($this->save()) { Yii::$app->session->setFlash('alert-success', 'Потребителят беше успешно блокиран.'); } else { Yii::$app->session->setFlash('alert-error', 'Възникна грешка при блокирането на потребителя.'); } } else { Yii::$app->session->setFlash('alert-error', 'Не съществува потребител с това потребителско име.'); } } public function banIp() { if ($this->save()) { Yii::$app->session->setFlash('alert-success', 'IP адресът беше успешно блокиран.'); } else { Yii::$app->session->setFlash('alert-error', 'Възникна грешка при блокирането на IP адреса.'); } } ``` } My controllers/MembersBansController.php: ``` public function actionList() { $membersBans = new MembersBans(); if ($membersBans->load(Yii::$app->request->post('banMember'))) { $membersBans->banMember(); } if ($membersBans->load(Yii::$app->request->post('banIp'))) { $membersBans->banIp(); } return $this->render('list', [ 'membersBans' => $membersBans, ]); } ``` views/members-bans/list: ``` <div class="the-box"> <?php $activeForm = ActiveForm::begin([ 'id' => 'banMember', 'enableClientValidation' => true, 'enableAjaxValidation' => true, 'validateOnSubmit' => true, 'validateOnChange' => true, 'validateOnType' => true, ]) ?> <?= $activeForm->field($membersBans, 'username', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control', 'placeholder' => 'Въведете потребителско име']); ?> <?= $activeForm->field($membersBans, 'end_date', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control datepicker', 'placeholder' => 'Въведете период на бана']); ?> <?= $activeForm->field($membersBans, 'reason', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control', 'placeholder' => 'Въведете причина за бана']); ?> <div class="form-group"> <?= Html::submitButton('Добави', ['type' => 'submit', 'class' => 'btn btn-default']) ?> </div> <?php ActiveForm::end()?> </div> <div class="the-box"> <?php $activeForm = ActiveForm::begin([ 'id' => 'banIp', 'enableClientValidation' => true, 'enableAjaxValidation' => true, 'validateOnSubmit' => true, 'validateOnChange' => true, 'validateOnType' => true, ]) ?> <?= $activeForm->field($membersBans, 'ban_ip', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control', 'placeholder' => 'Въведете IP адрес или цяла мрежа']); ?> <?= $activeForm->field($membersBans, 'end_date', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control datepicker', 'placeholder' => 'Въведете период на бана']); ?> <?= $activeForm->field($membersBans, 'reason', [ 'template' => '{label}{input}{hint}{error}' ])->textInput(['class' => 'form-control', 'placeholder' => 'Въведете причина за бана']); ?> <div class="form-group"> <?= Html::submitButton('Добави', ['type' => 'submit', 'class' => 'btn btn-default']) ?> </div> <?php ActiveForm::end() ?> </div> ``` And it doesn't seem to work. Any ideas?

Original source