Yii Framework Forum: Cgridview With Has_Many Relationship - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Cgridview With Has_Many Relationship Rate Topic: -----

#1 User is offline   Time Travel Mishap 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 07-March 13

Posted 11 March 2013 - 11:42 PM

I actually started writing this to ask for help, but found my error before I finished. Instead of letting it all go to waste I thought I would share my example. Hopefully it will help someone else.

I have the following relationship in my User model:

'email' => array(self::HAS_MANY, 'Email', 'user_id'), 


Now I know that CGridView and HAS_MANY relationships don't get along, but I'm stubborn and I had a special case. Each user has only one primary email so I wanted to identify this HAS_ONE relationship in the many emails of the user and not only use the primary email in CGridView, but also allow it to be contextually searched and filtered (ASC, DESC). This is how I did it:

User Model
class User extends CActiveRecord
{
        public $email_primary;

    	public function rules()
	{
		return array(
			array('email_primary', 'safe', 'on'=>'search'), 
		);
	}

	public function search()
	{

		$criteria=new CDbCriteria;

		$criteria->with = array(
		    'email'=>array(
		          'together'=>true
		     )
		);
		
		
		$criteria->compare('username',$this->username,true);
		$criteria->compare('create_time',$this->create_time);
		
		$criteria->compare('profile.lastname',$this->profile_lastname,true);
		$criteria->compare('profile.firstname',$this->profile_firstname,true);
		
		
		return new CActiveDataProvider($this, array(
			'criteria'=>$criteria, 
			'sort'=>array(
				'attributes'=>array(
					'email_primary'=>array(
						'asc'=>'email.email', 
						'desc'=>'email.email DESC', 
					),
					'*',
				),
			),
		));
	}
	
	public function primaryEmail() {
		foreach ($this->email as $email) {
			if($email->primary == 1)
			{
				return $this->email_primary = $email->email;
			}
		}
	}


Grid View

<?php $this->widget('zii.widgets.grid.CGridView', array(
	'id'=>'user-grid',
	'dataProvider'=>$model->search(),
	'filter'=>$model,
	'columns'=>array(
		array(
			'name'=>'email_primary', 
			'header'=>'Email',
			'value'=>'$data->primaryEmail()', 
		),
		array(
			'class'=>'CButtonColumn',
		),
	),
)); ?>


All questions and criticisms welcome!
1

#2 User is offline   RKA 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 19-February 13

Posted 14 March 2013 - 06:49 AM

Thanks for sharing this. I am also stuck up with relations.Myself has two tables 'student' and 'marks'.Aim is to display the student details along with marks. The query is correct joining two tables. The issue is not able to display the fields in the joined table(marks).

model page
-------
public function relations()
	{
		
		return array(
				'marks' => array(self::HAS_MANY, 'Marks', 'sID','joinType'=>'inner join'),
			
		);
		
	}

public function search()
	{
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.
	
		$criteria	        = new CDbCriteria;
		$criteria->with 	= "marks";
		$criteria->order	= "studentName asc";
		$criteria->compare('studentID',$this->studentID);
		$criteria->compare('studentName',$this->studentName,true);
		$criteria->compare('studentcity',$this->studentcity,true);
		$criteria->compare('marks.mark1',$this->mark1,true);
		//$criteria->compare('mark2',$this->mark2,true);
		//$criteria->compare('mark3',$this->mark3,true);
		return new CActiveDataProvider($this, array(
				'criteria'=>$criteria,
		));
	} 

---
controller page
---
public function actionIndex()
	{		
		$model = new ExtendedStudent();	
		$this->render('index',array('list'=>$model));
		
	}


View page
----
$this->widget('zii.widgets.grid.CGridView',array(
		'dataProvider'=>$list->search(),		
		'id'=>'studgrid',
		'columns'=>array(
				array(
						'id'=>'autoId',
						'class'=>'CCheckBoxColumn',
						'selectableRows'=> '10',						
					  ),
				array(
						'name'=>'studentName',

						'value'=>'CHtml::encode($data->studentName)'
					  ),
				array(
						  'name'=>'studentcity',
						  'header'=>'City',

						'value' => 'CHtml::encode($data->student->studentcity)'							
					),
				 array(
						'header'=>'M1',
						'name'=>'mark1',						
				 		'value' => '$data->marks==null?"":$data->marks->mark1',
				 	

				),
		)); 



Could you please tell how to show the joined table column in grid?Any help is appreciated.
0

#3 User is offline   Time Travel Mishap 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 07-March 13

Posted 14 March 2013 - 10:16 PM

Student HAS_MANY Marks and that I know of, you are not able to use this type of relationship without some customization on your part, such as in my original post.

To demonstrate the problem, here is your code but narrated from the perspective of the computer that's trying to run it.

  // Ok so were going to find some Students, here we go...

  // Found a Student row, ok great now what
  $criteria = new CDbCriteria;

  // With the students Marks, well he has 13 of them but alright what next 
  $criteria->with = "marks";

  // Oh so Im supposed to put put this student in a row, alright no problem
  $this->widget('zii.widgets.grid.CGridView',array(
    //... *snipped*

    // Students name, easy here you go
    array(
      'name'=>'studentName',
      'value'=>'CHtml::encode($data->studentName)'
    ),

    // Marks mark1, ok no probl...    wait a second
    // I have 13 marks here but can only put it into 1 row
    // What am I supposed to just pick one?
    // Well I guess I could... but then oh no, what if I pick the wrong one???
    // OH THE HUMANITY! FOR THE LOVE OF SCIEN...     *error*
    array(
      'header'=>'M1',
      'name'=>'mark1',						
      'value' => '$data->marks==null?"":$data->marks->mark1',
    ),
  ));


So maybe I had a little too much fun with that, but the point is you cant put multiple rows into 1. Which means we need to get our creative programming juices flowing and write a custom solution. Here's a couple possibilities:

  • Take the many Marks found a cram the data you need into one variable
  • Repeat the Student rows count(Marks) number of times

Option number one seems the easiest but comes with one caveat: you cant sort in the grid view with this column. Well, at least not with the example Im about to give you:

        // Add this to your Students model
	public function getMarks()
	{
		$data = '';
		foreach($this->mark as $mark)
		{
			$data .= $mark->mark1;
		}
		return $data;
	}


        // In grid view
        $this->widget('zii.widgets.grid.CGridView',array(
		'dataProvider'=>$list->search(),		
		'id'=>'studgrid',
		'columns'=>array(
                        // Call User->getMarks() to get a string of all Marks 
		        array(
			        'id'=>'M1',
				'value'=> array($model, 'getMarks'),
                        ),
                )
        ));			


This code isn't tested and still I'm a Yii rookie so you'll probably have to fix a few things.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users