Yii2 Multiple instances of the same model
Asked Answered
F

3

7

I want to get multiplie instance of the same model in my controller. I saw this wiki for Yii 1.1 and tried like that but in my code only last instance in form was acceble from controller my code is here (I commented code with error and variable values):

$model = new Person(['scenario' => 'create_update']);
$contractDate = new DatePart(); // DatePart is my own class
$contractExpirationDate = new DatePart(); // DatePart is my own class

if ($model->load(Yii::$app->request->post()) &&
    $contractDate->load(Yii::$app->request->post()) &&
    $contractExpirationDate->load(Yii::$app->request->post())){

    Yii::info(Yii::$app->request->post(),'test'); // only one instance of Person and one instance of DatePart are available here
    Yii::info($_POST['DatePart'],'test'); // only last instance of DatePart (contractExpirationDate in html form) is available here
    Yii::info($_POST['DatePart'][0],'test'); // Error: Undefined offset: 0
    Yii::info($_POST['DatePart'][1],'test'); // Error: Undefined offset: 1

    $model->save();
    return $this->redirect(['view', 'id' => $model->id]);
} else {
    return $this->render('create', [
        'model' => $model,
        'contractDate' => $contractDate,
        'contractExpirationDate' => $contractExpirationDate,
    ]);
}

It is my form view in _form.php:

<?php

use yii\helpers\Html;
//use yii\widgets\ActiveForm;
use kartik\widgets\ActiveForm;
use common\models\DataOperations;

/* @var $this yii\web\View */
/* @var $model app\models\Person */
/* @var $contractDate backend\viewModels\DatePart */
/* @var $contractExpirationDate backend\viewModels\DatePart */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="user-form">
    <?php
    $form = kartik\widgets\ActiveForm::begin(
        [
            'id' => $model->isNewRecord ? 'user-form-create' : 'user-form-update',
            'type' => ActiveForm::TYPE_VERTICAL,
            //'enableAjaxValidation' => true,
            'fieldConfig' => [
                //'autoPlaceholder'=>true
            ]
        ]);
    ?>

    <?= $form->field($model, 'name')->textInput(['maxlength' => 60]) ?>  
    <?= $form->field($model, 'family')->textInput(['maxlength' => 60]) ?>
    <?= $form->field($model, 'mobile')->textInput() ?>

    <?= $form->field($contractDate, 'year')->textInput() ?>
    <?= $form->field($contractDate, 'month')->textInput() ?>
    <?= $form->field($contractDate, 'day')->textInput() ?>

    <?= $form->field($contractExpirationDate, 'year')->textInput() ?>
    <?= $form->field($contractExpirationDate, 'month')->textInput() ?>
    <?= $form->field($contractExpirationDate, 'day')->textInput() ?>

    <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>  
</div>

It is log result for: Yii::info(Yii::$app->request->post(),'test') in debugger as you seen only last DatePart available but I have two DatePart model instance (contractDate and contractExpirationDate):

[
    '_csrf' => 'Vl81R0ZvMk1hD1oELT9aDzkIe3EPHFgiIBJTBhA9RD8GbFM.AhlVBw==',
    'Person' => [
        'name' => 'test name',
        'family' => 'test family',
        'mobile' => '09121212123',
    ],
    'DatePart' => [
        'year' => '2015',
        'month' => 'Jun',
        'day' => 'Mon',
    ],
]
Fomentation answered 19/7, 2014 at 6:32 Comment(3)
Means in your $model, only last value is inserted in table ?Dita
No I only get last model from DatePart type in controller post variable. I added some information to question. (log content)Fomentation
please post your view, what comes in $_POST is dependent on your form and how you submit it in the viewQuadripartite
S
13

Controller:

    $model = new Person(['scenario' => 'create_update']);
    $dates = [
        'contractDate' => new DatePart(),
        'contractExpirationDate' => new DatePart()
    ];
    if ($model->load(Yii::$app->request->post())) {

        if (Model::loadMultiple($dates, Yii::$app->request->post()) && Model::validateMultiple($dates)) {
            foreach ($dates as $date) {
                $date->save();
            }
            // or
            $contractDate = $dates['contractDate'];
            $contractExpirationDate = $dates['contractExpirationDate'];
            // ...... some logic

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

View Form:

<?= $form->field($dates, '[contractDate]year')->textInput() ?>
<?= $form->field($dates, '[contractDate]month')->textInput() ?>
<?= $form->field($dates, '[contractDate]day')->textInput() ?>

<?= $form->field($dates, '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($dates, '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($dates, '[contractExpirationDate]day')->textInput() ?>
Schaal answered 20/7, 2014 at 9:21 Comment(3)
Thanks @Schaal I think view have some error I got this error: Call to a member function formName() on a non-objectFomentation
I think that Model::loadMultiple() not work correctly.Fomentation
it is working @Fomentation you need to import the yii\base\Model (use \yii\base\Model)Redistrict
Y
6

To complement b24 answer.

// In View Form add foreach:

<?php foreach ($dates as $index => $date): ?>

<?= $form->field($date, '[contractDate]year')->textInput() ?>
<?= $form->field($date, '[contractDate]month')->textInput() ?>
<?= $form->field($date, '[contractDate]day')->textInput() ?>

<?= $form->field($date, '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($date, '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($date, '[contractExpirationDate]day')->textInput() ?>

<?php endforeach; ?>

// - or - add index

<?= $form->field($dates['contractDate'], '[contractDate]year')->textInput() ?>
<?= $form->field($dates['contractDate'], '[contractDate]month')->textInput() ?>
<?= $form->field($dates['contractDate'], '[contractDate]day')->textInput() ?>

<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]day')->textInput() ?>
Yezd answered 25/3, 2015 at 21:42 Comment(0)
H
0

This can be is solution for this problem :

http://www.yiiframework.com/forum/index.php/topic/53935-solved-subforms/page__p__248184#entry248184

Heresiarch answered 19/5, 2015 at 12:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.