📜 ⬆️ ⬇️

Step-by-step guide to save related data Yii

Intro


Recently, I began to learn the wonderful Yii framework. When developing, I was faced with the task of saving data from one form into several tables. Googling, I did not find a sane guide that explains the full meaning of this preservation. On the official Russian-language website, I found a short article from Alexander Makarov, but it, again, in general, demonstrates the “salt” of this method.
I decided to write this article, in the tutorial style, to give beginners the opportunity to visually see the full CRUD cycle when working with several models, and to those who are more experienced, criticize this decision, and explain “how not to do it”.

Formulation of the problem


It is necessary to create two tables for storing user data. One is called user - it is intended to store the user's login and password, his status and his global identifier, which will be used throughout the system. The second user_profile which is intended to store public data about the user, his first and last names, etc. The profile table is linked to the user table using a foreign key.
It is necessary to save and edit data about the user, from one single form, which includes the fields of both the user table and user_profile table

Creating database tables


Create two tables of this type.
user - the parent table where the user id is created
user_profile - child table, has user_id foreign key on parent table


')

Creating models


Using the gii code generator, we create models of these tables and name them, respectively, User and UserProfile.
Also with the help of gii we will create a CRUD for the User model (I note that for the UserProfile model, I intentionally do not create a CRUD, since we do not need it)

Refinement of the parent model


In the parent model, we need to add fields from the child model:
<?php class User extends CActiveRecord { ////  public $name; public $first_name; public $description; ////  ... public function attributeLabels() { return array( 'id' => 'ID', 'login' => 'Login', 'password' => 'Password', 'status' => 'Status', ////  'name'=>'', 'first_name'=>'', 'description'=>'' ////  ); } 


And also define the AfterSave method by adding the code:
 ////  protected function afterSave() { parent::afterSave(); if($this->isNewRecord){ //     ,     //            $user_profile = new UserProfile; $user_profile->user_id = $this->id; $user_profile->name = $this->name; $user_profile->first_name = $this->first_name; $user_profile->description = $this->description; $user_profile->save(); } else { //        UserProfile::model()->updateAll(array( 'user_id' =>$this->id, 'name' => $this->name, 'first_name'=>$this->first_name, 'description'=>$this->description ), 'user_id=:user_id', array(':user_id'=> $this->id)); } } ////  


Now step by step what happened here:
1) added three public variables that correspond to the fields of the UserProfile model,
now these are new fields in the User model
  public $name; public $first_name; public $description; 

2) in the attributeLabels () method, create descriptions for new fields
  'name'=>'', 'first_name'=>'', 'description'=>'' 

3) Now we create the afterSave method, which works after saving the data in the User model,
and right there we will save the data in the UserProfile .

Thus, we check what is happening now: creating a new record or editing an existing one.
  if($this->isNewRecord){ 


If a new user has been created, then:


If it was an editing operation, then:

 UserProfile::model()->updateAll(array( 'user_id' =>$this->id, 'name' => $this->name, 'first_name'=>$this->first_name, 'description'=>$this->description ), 'user_id=:user_id', array(':user_id'=> $this->id)); 

Here, the values ​​are populated from the actionUpdate action of the UserController controller

Controller refinement


Now open the newly-generated UserController controller.
In it, we have to fix two actions actionCreate and actionUpdate ,
and one loadModel function

actionCreate

Assign values ​​to public variables that we added to the model.
From here, the data is used, in the afterSave method
 public function actionCreate() { $model=new User; if(isset($_POST['User'])) { $model->attributes=$_POST['User']; ////  $model->name = $_POST['User']['name']; $model->first_name = $_POST['User']['first_name']; $model->description = $_POST['User']['description']; ////  if($model->save()) $this->redirect(array('view','id'=>$model->id)); } $this->render('create',array( 'model'=>$model, )); } 


actionUpdate

Here, a similar process occurs as when creating a user.
  public function actionUpdate($id) { $model=$this->loadModel($id); if(isset($_POST['User'])) { $model->attributes=$_POST['User']; ////  $model->name = $_POST['User']['name']; $model->first_name = $_POST['User']['first_name']; $model->description = $_POST['User']['description']; ////  if($model->save()) $this->redirect(array('view','id'=>$model->id)); } $this->render('update',array( 'model'=>$model, )); } 


loadModel

Here we add such lines.
We need to load data from the user profile table, found by its user_id.
  public function loadModel($id) { $model=User::model()->findByPk($id); ////  $modelprofile=UserProfile::model()->find('user_id=:user_id', array(':user_id'=> $id)); $model->name = $modelprofile->name; $model->first_name = $modelprofile->first_name; $model->description = $modelprofile->description; ////  if($model===null) throw new CHttpException(404,'The requested page does not exist.'); return $model; } 

This is necessary for the data to be loaded into the form when we click on the Update User link,
and to display information in a viewport

Completion of the parent form


In the form that is located at the address protected / views / user / _form.php
we need to add elements to enter the user's first name, last name and description
 <?php <div class="form"> <?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'user-form', 'enableAjaxValidation'=>false, )); ?> <p class="note">Fields with <span class="required">*</span> are required.</p> <?php echo $form->errorSummary($model); ?> <div class="row"> <?php echo $form->labelEx($model,'login'); ?> <?php echo $form->textField($model,'login',array('size'=>45,'maxlength'=>45)); ?> <?php echo $form->error($model,'login'); ?> </div> ..... ////  <div class="row"> <?php echo $form->labelEx($model,'name'); ?> <?php echo $form->textField($model,'name',array('size'=>45,'maxlength'=>45)); ?> <?php echo $form->error($model,'name'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'first_name'); ?> <?php echo $form->textField($model,'first_name',array('size'=>45,'maxlength'=>45)); ?> <?php echo $form->error($model,'first_name'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'description'); ?> <?php echo $form->textField($model,'description',array('size'=>45,'maxlength'=>45)); ?> <?php echo $form->error($model,'description'); ?> </div> ////  <div class="row buttons"> <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?> </div> <?php $this->endWidget(); ?> </div><!-- form --> 


Finalization of the presentation


The view file, which is located at the protected / views / user / view.php address , we also add our new fields to the detailed display widget
 <?php .... <?php $this->widget('zii.widgets.CDetailView', array( 'data'=>$model, 'attributes'=>array( 'id', 'login', 'password', 'status', ////  'name', 'first_name', 'description' ////  ), )); ?> 


and in the auxiliary file, protected / views / user / _view.php, we add the following:
 <?php /* @var $this UserController */ /* @var $data User */ ?> <div class="view"> <b><?php echo CHtml::encode($data->getAttributeLabel('id')); ?>:</b> <?php echo CHtml::link(CHtml::encode($data->id), array('view', 'id'=>$data->id)); ?> <br /> ... ////  <b><?php echo CHtml::encode($data->getAttributeLabel('name')); ?>:</b> <?php echo CHtml::encode($data->name); ?> <br /> <b><?php echo CHtml::encode($data->getAttributeLabel('first_name')); ?>:</b> <?php echo CHtml::encode($data->first_name); ?> <br /> <b><?php echo CHtml::encode($data->getAttributeLabel('descrption')); ?>:</b> <?php echo CHtml::encode($data->descrption); ?> <br /> ////  </div> 


Check result


Now, if everything is done as described above, go to
localhost / YourProjectName / index.php? r = user / create



Fill in all the fields, and click Create .
After that, you should see this result:



If we want to edit this entry, click on the Update User link,
our form will fill with data



Outro


I hope that the article will be useful for novice developers, and will save time when searching for a similar solution.
Any constructive criticism of experienced developers, inspired by personal examples, is accepted.

Thanks for attention!

Used Books

The article from the recipes section " Saving related data ".

Source: https://habr.com/ru/post/200478/


All Articles