Nested Form With Multiple Models

Hi,

I’m trying to make a form bind with a table “Personne” which contains a nested form that correspond to a foreign key Personne.fk_profil which is anonther data model.

I success to make something working but too much code than i expected. Knowing that i’m going to make lot of forms with many relations, i’m looking for the best way to do this.

What i expect is that the main form "Personne" recognize the child form "Profil" when i store POST data in attributes property of the Personne object and create automatically an object from it (instead of doing this manually).

Any help would be great.

Thanks

Can you post the action code that you’re currently using?

My previous explanation was more straightforward than what i’m really doing but it should be understandable.




$pers = Pers::getPers($persId); // Either $pers->proprio OR $pers->personnel is set (null  if no data)

	

		if (!empty($_POST['Pers']) AND ($pers->proprio AND !empty($_POST['Pers']['proprio']) XOR ($pers->personnel AND !empty($_POST['Pers']['personnel'])))) {

			

			if ($pers->proprio) {

				$pers->proprio->attributes = $_POST['Pers']['proprio'];

			}

			elseif ($pers->personnel) {

				$pers->personnel->attributes = $_POST['Pers']['personnel'];

			}

			

			if ($pers->validate()) {

				

				if ($pers->proprio) {

					$pers->proprio->save(false);

				}

				

				if ($pers->personnel) {

					$pers->personnel->save(false);

				}

				

				$pers->attributes = $_POST['Pers'];

				$pers->save(false);

				

				$this->redirect(array('/pers'));

			}

			else {

				$this->render('edit', ['pers' => $pers]);

			}

		}

		else {

			$this->render('edit', ['pers' => $pers]);		



Assuming you’re using InnoDB, you should use transactions. Your whole action should look more like this:




$pers = Pers::getPers($persId); // Either $pers->proprio OR $pers->personnel is set (null  if no data)


if (!empty($_POST['Pers']) AND ($pers->proprio AND !empty($_POST['Pers']['proprio']) XOR ($pers->personnel AND !empty($_POST['Pers']['personnel']))))

{

        $transaction = $pers->dbConnection->beginTransaction();


        try

        {

                $pers->attributes = $_POST['Pers'];

                if (!$pers->save())

                        throw new Exception();


                if ($pers->proprio)

                {

                        $pers->proprio->attributes = $_POST['Pers']['proprio'];

                        if (!$pers->proprio->save())

                                throw new Exception();

                }

                else if ($pers->personnel)

                {

                        $pers->personnel->attributes = $_POST['Pers']['personnel'];

                        if (!$pers->personnel->save())

                                throw new Exception();

                }


                $transaction->commit();

                $this->redirect(array('/pers'));

        }

        catch (Exception $ex)

        {

                $transaction->rollback();

        }

}


$this->render('edit', ['pers' => $pers]);



Your scenario is less straightforward than a standard one, which is why the code is a little busier.

The problem is that when i’m doing this :




$pers->attributes = $_POST['Pers'];



"$pers->proprio" is no longer an object but is an array like in $_POST.

Hmm, I wouldn’t think it would assign proprio unless you have a validation rule defined for an attribute with that name. Can you post your rules for the Pers class?

Fine you were right :)

I wondered if there wasn’t a way to “map” automatically form elements to the model.

In fact, for Yii, a form and a model is the same, there isn’t a specific object for each form.

Isn’t it possible to have a form class that add form elements based on the associated model ? In that way, names could be different in the form then in the model for example.

I’m very impressed by Yii ORM features but disappointed about form management which is maybe the most important thing in a website.

I wish to be able to retrieve the same structure get from the ORM with joins from a nested form…