Using CGridView with 2 data providers?

I’d like to set up a CGridView, or whatever might be appropriate to do the following. I’m looking to display data from 2 different tables in one view. The data is from a table called poll, and another table called vote.

Poll (one) <------ Vote (many) . Poll is referenced by vote

Anywho, I’d like it to look something like this

Poll Description Poll result Room started User Vote <-----(table headings)

poll # 1 Yes 233 5.00 pm Jim Yes

                                                                               joe         No


                                                                               Jill         Yes


                                                                               Jack       Yes

poll # 2 No 224 6.00pm Dan No

                                                                               Dave      No


                                                                               Darryl    No

So poll description, poll result, room, and started would all be data from the poll table. User and vote are data from the Vote table. Is this possible?

The text spacings got all messed up there, I’ll have to try repost it. My questions still stands though, is there anyway to display data from 2 different tables in the one CGridview? Am I right in saying that a dataprovider corresponds to one table, and a gridview can only use one dataprovider?

It’s easy to display HAS_MANY related items in a CGridView, only if you dont’t want it to look very nice.

This is a quick and dirty example to show the related data in CGridView.




// in view file

// $model is an instance of Poll that conveys the search parameters for the grid

$this->widget('zii.widgets.grid.CGridView', array(

	'dataProvider' => $model->search(),

	'columns' => array(

		'description',

		'result',

		'room',

		array(

			'header' => 'User',

			'type' => 'ntext',

			'value' => '$data->ShowAllVoteUsers()',

		),

		array(

			'header' => 'Vote',

			'type' => 'ntext',

			'value' => '$data->ShowAllVotes()',

		),

	),

));


// in Poll model file

...

public function relations()

{

	return array(

		'votes' => array(self::HAS_MANY, 'Vote', 'poll_id'),

	);

}

...

public function ShowAllVoteUsers()

{

	$users = array();

	foreach($this->votes as $vote)

		$users[] = $vote->user;

	return implode("\n", $users);

}

public function ShowAllVotes()

{

	$votes = array();

	foreach($this->votes as $vote)

		$votes[] = $vote->result ? 'Yes' : 'No';

	return implode("\n", $votes);

}



Well first of all, thanks a million for your response, it’s been an amazing help. I need to do this though, can you advise.

In the ShowAllVotes function I need to check a value in the poll table. Instead of $vote->result ? ‘Yes’:‘No’; I’d need something along the lines of


 $poll->after_settings == 'Voter only' ? ' ': $vote->result; 

Meaning that if the after_settings attribute has value ‘Voter only’ in the poll table then don’t display the vote result, if it doesn’t have that value display it. Hope that makes sense.

Thanks again

That’s simply something you need to add to the ‘WHERE’ clause in your query.


... WHERE tableName.after_settings != 'Voter only'

Thanks, think I got that part now. On another note though, I’m new to php and yii so softarks example helped me out big time. His example searches for one poll object in the db_poll table and displays it in the gridview . How could I make it so that it returns all poll objects where their room_name attributes were of a specific value. Would I have to add a filter or condition in the search function? Can somebody show me a code example of how I might do that? What I’m trying to achieve is roughly this.


$this->widget('zii.widgets.grid.CGridView', array(

        'dataProvider' => $poll->search('room_name=?','this room'),

This is my psuedo code like way of trying to explain, I realize this syntax is probably way off, just trying to better explain what it is I’m trying to achieve.

Remember, a dataProvider is still an AR object. Anything you might use with a find or findAll() has a similar function in the dataProvider object.

Ok cool, thanks. This is my first yii project, as well as my first php project, as well as my first time using MVC architecture. It’s all a bit overwhelming at times but the site’s been a great help.

I’m only a few months ahead of you so I understand!

Ah, so you feel my pain. I’m still having trouble getting this to work though. Just to recap, here’s what I’m trying to do.


<div id="DisplayPollInfo">

<?php    

    if(isset($poll)){

    $this->widget('zii.widgets.grid.CGridView', array(

        'dataProvider' => $poll->search(),

        'columns' => array(

                'poll_description',

                'poll_result',

                'room_name',

                'started_by',

                array(

                        'header' => 'Voter(s)',

                        'type' => 'ntext',

                        'value' => '$data->ShowAllVoteUsers()',

                ),

                array(

                        'header' => 'Vote(s)',

                        'type' => 'ntext',

                        'value' => '$data->ShowAllVotes()',

                ),

                array(

                        'header' => 'Opened',

                        'type' => 'ntext',

                        'value' => '$opened',

                ),

                array(

                        'header' => 'Closed',

                        'type' => 'ntext',

                        'value' => '$closed',

                ),

        ),

 ));

    

 }

How can I modify/filter my search. What I’d like to do is , instead of ‘dataProvider’ => $poll->search(), I want only to show polls with a certain room_name, so somethng like ‘dataProvider’ => $poll->search(where poll room number = this room). That’s a pseudo code way of explaining my problem.

Also, I’d like to perform an operation on some data before showing it in the CGridview


array(

                        'header' => 'Opened',

                        'type' => 'ntext',

                        'value' => '$opened',

                ),

                array(

                        'header' => 'Closed',

                        'type' => 'ntext',

                        'value' => '$closed',

                ),

The two value elements here, ‘Opened’ and ‘Closed’. I’d like to take 2 fields from the poll db table, perform an action on them to manipulate them, then insert them into those values, if that makes sense? What would be the syntax for that? Again, a rough pseudo code way of illustrating what I mean is

‘value’ => ‘call function using value from db poll as input to that function, then take the return value of that function and put it in here’,

Can somebody please help?

Sure.

Best thing to do to learn searching/filtering gridviews is to look at the ‘Advanced Search’ that Gii generates for you. Everything you need is there so long as you make sure your form GETs instead of POSTs the parameters.

If you want to transform the data before displaying it, create methods (functions) in your model that return what you want. Call them from the gridview like this:




array(

  'header'=>'whatever',

  'value'=>'MyModel::model()->getOption($data)',

)



$data contains the data for that particular ‘cell’ in the grid. So you can call out to a model method, manipulate it, and return a value.