You are viewing revision #1 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.
This tutorial shows how to use a model to save and validate related (MANY_MANY) models.
In this tutorial you will find
- Validating model as a whole including its related models
- Collecting data for the model and its related models (tabular input)
- Displaying errors from the related models.
- Saving the primary model and its related models.
- Natural association ( $model->students = array($studentOne, $studentTwo); )
Usage:
- Get the code from github https://github.com/xavierjohn/yii-tabularinput
- Create a MySQL schema called classroom
- Run the migration to create the tables and some sample courses
./protected/yiic migrate
./protected/yiic createCourses
Run the site.
Details:
Validation of the Course model is done by over loading the validate method. This method can be used to validate the model as a whole, like prevent students with the same name.
public function validate($attributes = null, $clearErrors = true) {
$isValid = parent::validate($attributes, $clearErrors);
foreach ($this->students as $student) {
if ($student->validate() == false) {
$isValid = false;
$this->addErrors($student->getErrors());
}
}
return $isValid;
}
Next we overload the save method to save all related models.
public function save($runValidation = true, $attributes = null) {
if ($runValidation) {
if ($this->validate($attributes) == false)
return false;
}
foreach ($this->students as $student) {
$student->save(false);
}
return parent::save(false, $attributes);
}
Now I can create a course model and its related students.
Snip from protected/tests/unit/CourseTest.php
$courseName = 'testCourse';
$studentOne = new Student();
$studentOne->first_name = 'Firsty';
$studentOne->last_name = 'Test';
$studentTwo = new Student();
$studentTwo->first_name = 'Secondy';
$studentTwo->last_name = 'Test';
$model = new Course();
$model->name = $courseName;
$model->description = 'This course was created for testing purpose';
$model->students = array($studentOne, $studentTwo);
if ($model->save() == true) {
echo 'Successfully created ' . $model->name . PHP_EOL;
} else {
echo 'Failed to create ' . $model->name . PHP_EOL;
print_r($model->Errors);
}
EAdvancedArBehavior is used to update the relationship table. http://www.yiiframework.com/extension/eadvancedarbehavior/
To collect tabular input of students for a course I go through the Student collection as
if (isset($_POST['Course'])) {
$model->attributes = $_POST['Course'];
$model->students = CourseController::assignStudents($model, $_POST['Student']);
CourseController::assignStudents is defined as
public static function assignStudents($model, $items_posted) {
$students = array();
foreach ($items_posted as $item_post) {
$student = CourseController::findStudent($model, $item_post['id']);
if (is_null($student)) {
$student = new Student();
}
unset($item_post['id']); // Remove primary key
$student->attributes = $item_post;
array_push($students, $student);
}
return $students;
}
public static function findStudent($model, $id) {
$student = null;
foreach ($model->students as $s) {
if ($s->id == $id) {
$student = $s;
}
}
return $student;
}
I got the idea to solve the tabular input from http://www.yiiframework.com/extension/ztabularinputmanager/
@Xavier John
good work :-)
@Xavier John
How to limit row ??
Excellent
Very informative and working solution !!
@Xavier John
sir i follow your tutorial, it works on my system but when i put time picker the picker is not working.. here is my code in my time picker.
<?php $this->widget('application.extensions.jui_timepicker.JTimePicker', array(
'model'=>$model, 'attribute'=>"[$id]time", 'options'=>array( 'showPeriod'=>false, 'hours'=>array('starts'=>07, 'ends'=>18), ), 'htmlOptions'=>array('size'=>5,'maxlength'=>5), ));?>
datepicker in partial render
awesome. It works perfectly. But:
I needed a datepicker in the course/form/_studentRow. It just doesn't show up. When I put datepicker in course/_form, it does work.
what is wrong?
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.