Yii Framework Forum

Insert Multiple data of same model using one form


(Byndstd) #1

Hi I’m using Yii2 advanced and I’m trying to insert multiple data of one model using the same form it’s like invoices system inserting multiple products by same form, it’s for inserting data of student one then student 2 then student 3 … at once but I didn’t succeed.
My View File is :

<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, '[0]studentName')->textInput(['maxlength' => true])->label('NAME') ?>

    <?= $form->field($model, '[0]studentEmail')->textInput(['maxlength' => true])->label('EMAIL') ?>

    <?= $form->field($model, '[0]studentCode')->textInput(['maxlength' => true])->label('CODE') ?>

    <!--  -->

    <?= $form->field($model, '[1]studentName')->textInput(['maxlength' => true])->label('NAME') ?>

    <?= $form->field($model, '[1]studentEmail')->textInput(['maxlength' => true])->label('EMAIL') ?>

    <?= $form->field($model, '[1]studentCode')->textInput(['maxlength' => true])->label('CODE') ?>

    <!--  -->

    <?= $form->field($model, '[2]studentName')->textInput(['maxlength' => true])->label('NAME') ?>

    <?= $form->field($model, '[2]studentEmail')->textInput(['maxlength' => true])->label('EMAIL') ?>

    <?= $form->field($model, '[2]studentCode')->textInput(['maxlength' => true])->label('CODE') ?>

    ....    

    <?= $form->field($model, 'note')->textInput(['maxlength' => true])->label('NOTE') ?>

    <div class="form-group">
        <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
    </div>

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

And my controller create action is :

public function actionCreateClass($ssid)
    {
        $program = new Program();  $model = new ClassC();  $session = $this->findSession($ssid)

        if ($model->load(Yii::$app->request->post())) 
        {
            $program->title = 'PHP'. date('Y') .$session->title;
            $program->note = $model->note;
            $program->save();

            foreach ($model->studentCode as $SC)
            {
                $student = $this->findStudent($SC);

                $model;
                $model->program = $program->program_id;
                $model->save();
            }

            return $this->redirect(['programe', 'id' => $program->program_id]);
        }

        return $this->render('createClass', [
            'model' => $model,
        ]);

I tried using var_dump to know what I get as return but my var_dump return NULL in var_dump($model). I also tried to use

(Model::loadMultiple($model, Yii::$app->request->post())) but I get error

Call to a member function formName() on array


(Softark) #2

In the foreach loop above, you are using a value named $model. But it will collide with the $model you have declared at the beginning of the method. You have to use other name for it.

And would you please explain us about the model ClassC? What fields does it have?


(Byndstd) #3

My model ClassC has (studentName, studentEmail, studentCode, program);
My model Program() has (title; note, program_id; ClassC[] $classcs; ) program_id is auto_increment;


(Softark) #4

Are Program and ClassC ActiveRecords?
Could you show us the table schemas of the relevant tables?


(Byndstd) #5

Program Model

namespace frontend\models;

use Yii;

/**
 * This is the model class for table "program".
 *
 * @property int $program_id
 * @property string $title
 * @property string $note
 *
 * @property Classc[] $classcs
 */
class Program extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'program';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['title'], 'string', 'max' => 100],
            [['note'], 'string', 'max' => 300],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'program_id' => 'Program ID',
            'title' => 'Title',
            'note' => 'Note',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getClasscs()
    {
        return $this->hasMany(ClassC::className(), ['program' => 'program_id']);
    }

    /**
     * {@inheritdoc}
     * @return \frontend\queries\ProgramQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new \frontend\queries\ProgramQuery(get_called_class());
    }
}

ClassC Model

namespace frontend\models;

use Yii;

/**
 * This is the model class for table "classc".
 *
 * @property int $student_id
 * @property string $studentName
 * @property string $studentEmail
 * @property string $studentCode
 * @property int $program
 *
 * @property Program $program0
 * @property Student $student
 */
class ClassC extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'classc';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['student_id', 'program'], 'required'],
            [['student_id', 'program'], 'integer'],
            [['studentName', 'studentEmail'], 'string', 'max' => 200],
            [['studentCode'], 'string', 'max' => 100],
            [['program'], 'exist', 'skipOnError' => true, 'targetClass' => Program::className(), 'targetAttribute' => ['program' => 'program_id']],
            [['student_id'], 'exist', 'skipOnError' => true, 'targetClass' => Student::className(), 'targetAttribute' => ['student_id' => 'student_id']],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'student_id' => 'Student ID',
            'studentName' => 'Student Name',
            'studentEmail' => 'Student Email',
            'studentCode' => 'Student Code',
            'program' => 'Program',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProgram0()
    {
        return $this->hasOne(Program::className(), ['program_id' => 'program']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getStudent()
    {
        return $this->hasOne(Student::className(), ['student_id' => 'student_id']);
    }

    /**
     * {@inheritdoc}
     * @return \frontend\queries\ClasscQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new \frontend\queries\ClasscQuery(get_called_class());
    }
}

this is my models of PROGRAM and CLASSC


(Softark) #6

OK. I think I understand what you want to do.

Unfortunately, the otherwise perfect guide is a little too short on this matter and not yet completed. But please read the following sections again.
(https://www.yiiframework.com/doc/guide/2.0/en/input-tabular-input and
https://www.yiiframework.com/doc/guide/2.0/en/input-multiple-models)

What I suggest here is also far from perfect. It’s just a quick and dirty sample.

The controller code would be like this:

public function actionCreateClass($ssid)
{
    $program = new Program();
    $classcs = [];
    for ($i = 0; $i < 3; $i++) {
        $classcs[] = new ClassC();
    }

    if ($program->load(Yii::$app->request->post()) && 
            Model::loadMultiple($classcs, Yii::$app->request->post()) {
        if ($program->validate() && Model::validateMultiple($classcs)) {
            $session = $this->findSession($ssid)
            $program->title = 'PHP'. date('Y') .$session->title;
            $program->save();
            foreach ($classcs as $cc)
            {
                $student = $this->findStudent($cc->studentCode);
                $cc->studend_id = $student->student_id;
                $cc->program = $program->program_id;
                $cc->save();
            }
            return $this->redirect(['programe', 'id' => $program->program_id]);
        }
    }

    return $this->render('createClass', [
        'program' => $program,
        'classcs' => $classcs,
    ]);
}

And the view:

<?php $form = ActiveForm::begin(); ?>
<?php
foreach ($classcs as $index => $classc) {
    echo $form->field($classc, "[$index]studentName")->textInput(['maxlength' => true])->label('NAME');
    echo $form->field($classc, "[$index]studentEmail")->textInput(['maxlength' => true])->label('EMAIL');
    echo $form->field($classc, "[$index]studentCode")->textInput(['maxlength' => true])->label('CODE');
}
?>

<?= $form->field($program, 'note')->textInput(['maxlength' => true])->label('NOTE') ?>
<div class="form-group">
    <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>

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

As you see, we use program and classcs instead of model here in order to handle 2 kinds of model.


(Byndstd) #7

after click submit it does not enter

if ($program->load(Yii::$app->request->post()) && Model::loadMultiple($classcs, Yii::$app->request->post()) { if ($program->validate() && Model::validateMultiple($classcs)) {

I don’t know why

I even removed validate and still not enter the if condition
if ($program->load(Yii::$app->request->post()) && Model::loadMultiple($classcs, Yii::$app->request->post()) {
but not enter the if condition


(Softark) #8

Would you please check the content of Yii::$app->request->post() ?


(Byndstd) #9

It’s repeat only the 3

I used only model::

the var_dump:

    if (Model::loadMultiple($classcs, Yii::$app->request->post()))
{
	foreach ($classcs as $classc)
	{
		var_dump(Yii::$app->request->post());
	}
	die;
}

Result :

C:\wamp\www\nacer\frontend\controllers\ProgramController.php:84:
array (size=3)
  '_csrf-frontend' => string 'j1WWH4E-_D3mX_H0UhoK_dL0SwfZ0OguFOLI0cQ4P6fkB8B86k-fDqU2m5s5VDzOs6AUTY2Dg0NLleWJlVpF7g==' (length=88)
  'ClassC' => 
    array (size=3)
      0 => 
        array (size=3)
          'studentName' => string '3' (length=1)
          'studentEmail' => string 'gama@gama.gama' (length=14)
          'studentCode' => string 'st003' (length=5)
      1 => 
        array (size=3)
          'studentName' => string '2' (length=1)
          'studentEmail' => string 'beta@beta.beta' (length=14)
          'studentCode' => string 'st002' (length=5)
      2 => 
        array (size=3)
          'studentName' => string '1' (length=1)
          'studentEmail' => string 'mega@mega.mega' (length=14)
          'studentCode' => string 'st001' (length=5)
  'Program' => 
    array (size=2)
      'title' => string '' (length=0)
      'note' => string '' (length=0)
C:\wamp\www\nacer\frontend\controllers\ProgramController.php:84:
array (size=3)
  '_csrf-frontend' => string 'j1WWH4E-_D3mX_H0UhoK_dL0SwfZ0OguFOLI0cQ4P6fkB8B86k-fDqU2m5s5VDzOs6AUTY2Dg0NLleWJlVpF7g==' (length=88)
  'ClassC' => 
    array (size=3)
      0 => 
        array (size=3)
          'studentName' => string '3' (length=1)
          'studentEmail' => string 'gama@gama.gama' (length=14)
          'studentCode' => string 'st003' (length=5)
      1 => 
        array (size=3)
          'studentName' => string '2' (length=1)
          'studentEmail' => string 'beta@beta.beta' (length=14)
          'studentCode' => string 'st002' (length=5)
      2 => 
        array (size=3)
          'studentName' => string '1' (length=1)
          'studentEmail' => string 'mega@mega.mega' (length=14)
          'studentCode' => string 'st001' (length=5)
  'Program' => 
    array (size=2)
      'title' => string '' (length=0)
      'note' => string '' (length=0)
C:\wamp\www\nacer\frontend\controllers\ProgramController.php:84:
array (size=3)
  '_csrf-frontend' => string 'j1WWH4E-_D3mX_H0UhoK_dL0SwfZ0OguFOLI0cQ4P6fkB8B86k-fDqU2m5s5VDzOs6AUTY2Dg0NLleWJlVpF7g==' (length=88)
  'ClassC' => 
    array (size=3)
      0 => 
        array (size=3)
          'studentName' => string '3' (length=1)
          'studentEmail' => string 'gama@gama.gama' (length=14)
          'studentCode' => string 'st003' (length=5)
      1 => 
        array (size=3)
          'studentName' => string '2' (length=1)
          'studentEmail' => string 'beta@beta.beta' (length=14)
          'studentCode' => string 'st002' (length=5)
      2 => 
        array (size=3)
          'studentName' => string '1' (length=1)
          'studentEmail' => string 'mega@mega.mega' (length=14)
          'studentCode' => string 'st001' (length=5)
  'Program' => 
    array (size=2)
      'title' => string '' (length=0)
      'note' => string '' (length=0)

(Softark) #10

Model::loadMultiple($classcs, Yii::$app->request->post()) is working fine, because your var_dump is inside the if block.

I think that Model::validateMultiple($classcs) is failing because student_id and program are required in the rules of ClassC.

Would you please try validateMultiple with the 2nd parameter like this?

Model::validateMultiple($classcs, ['studentName', 'studentEmail', 'StudentCode'])

https://www.yiiframework.com/doc/api/2.0/yii-base-model#validateMultiple()-detail


(Byndstd) #11

Thank you so much for your help, I can’t thank you enough. Well I actually well use only Yii::$app->request->post() it seems doing the job for me.
Thank you again thank you