Yii 1.1: Tabular Input, Validating and Saving related models


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); )


./protected/yiic migrate
./protected/yiic createCourses

Run the site.


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;
        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) {
    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;

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/

Total 5 comments

#19575 report it
pavla at 2015/09/14 03:58am
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?

#18145 report it
raiethan at 2014/09/16 04:22am
@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), ));?>
#16216 report it
nairgh at 2014/01/30 12:46pm

Very informative and working solution !!

#15361 report it
masdib.banget at 2013/11/01 12:35am
@Xavier John

How to limit row ??

#14627 report it
Rajith R at 2013/08/30 01:57am
@Xavier John

good work :-)

Leave a comment

Please to leave your comment.

Write new article