How to use a DataProvider

I am at my wits end again with something that should be basic, and other people make it work, but every time I try, I either get gobbledygook or errors.

All I want to do is step through the results of a search in a dataprovider, and make an array of the id attributes. This should be easy, but it appears to be arcane.

Say I have a model Balls. I want to search for all the red Balls, display the records in a CGridView, let the user select some of the records, then return the selected records and an array of ALL the ids to the BallsController. Should be easy, right? But I cannot for the life of me figure out how to step through the records in the dataprovider. I do not understand the structure of a CActiveDataProvider or how to access it. It appears from the class reference that the getData method should help, but I cannot get meaningful data out of that either.

Please somebody explain it to me.

Also, when you create a dataprovider, then pass it to a CGridView, when is the actual SQL search run? I gather the view script runs it, but in what method?

Thank you in advance to anyone who takes the time to explain all this to me.

Hi fpolli,

CActiveDataProvider is mostly used for displaying purpose together with a CGridView or a CListView.

It’s a kind of “Search Query Executor” that returns an array of db records responding to a request from a CGridView or a CListView.

We usually don’t have to trigger the query execution by ourselves. And we don’t care much about the returned array. Those things are for the grid or the list to take care of. We only have to write the code for the grid or the list to display each single data row.

And, we usually do not use CActiveDataProvider to UPDATE db records.

I would design your use case as a series of several phases.

  1. Initial page display

This is done by a controller action on the server.

It should produce a HTML output and send it to the user’s browser.

We will use CActiveDataProvider and CGridView to display the page that shows all the "Red" balls.

  1. Selection of the balls

This should happen on the user’s browser.

The user will select the balls that he wants to change color from "Red" to "Orange", for example.

The selection can be represented by a check box on each row, and you have to wrap the grid with a form.

  1. Submission of the selection to the server

The user will press the ‘Change Color to Orange’ button.

The browser will submit a form with the selected ids of balls.

  1. Receive the submission and update the db

This is on the server side again.

We will receive the selected ids of the balls and save changes to the db.




foreach($selected_ids as $id)

{

    $model = Ball::model()->findByPk($id);

    $model->color = "Orange";

    $model->save();

}



Note that we don’t need CActiveDataProvider here.

  1. Update page display

We will use CActiveDataProvider and CGridView once again to display the updated page. It’s just the same with phase 1).

Well, does it make some sense?

Yes, thank you. I’ve been having a hard time figuring out how to reference the dataprovider. What does it belong to? I went into the source code, and it looks like at the top level you can use $this->dataProvider, and in lower levels, use $this->grid->dataProvider.

Your explanation will be extremely useful to me, and I appreciate the time you took.

Um, yes. When "$this" is a grid, then "$this->dataProvider" is the data provider, and when "$this" is a data column in a grid, then "$this->grid->dataProvider" is it.

CBaseListView::dataProvider

CGridColumn::grid

Accustom yourself to look up the reference. I assure you that it will be a great fun. :)

BTW, why do you want to access the data provider from the grid or the column?

I’ve already looked at the class reference many, many times, but it is hard to understand when you don’t already understand it. When I went to the source files, I started to figure it out. You explain things a lot more simply than they are in the class reference.

I wanted to pass a list of ids of all the records to a controller function.

Yeah, that’s true in a sense, indeed.

Until you’ve got a big picture of the framework in mind, it’s a little bit frustrating. I also had a hard time when I started learning Yii.

Especially the grid and the data provider were the complete mystery to me. I mean the gii-generated admin page. I couldn’t understand why it could work like that.

Don’t worry. :D

I see.

But on which phase of the use case do you want to use the list? And for what reason and how?

Yes, the grid and dataprovider were a mystery to me until last night when I read your post and the source of CGridView and its parents. Now it is just like my wife – I understand a lot and know how to recognize certain behaviors, but still partially a mystery! :D

Basically I wanted to pass the list of all ids, and the list of selected ids from the view to the controller, then strike the selected from the overall list and generate a new record set. But having thought it through I have gone in a bit of a different direction, because pagination with the gridview screws everything up.

Thank you for your help. It’s nice to see a forum where more people are interested in helping than in making people feel stupid.

Yeah, the friendly community is one of the reasons why I love Yii.

OK, why don’t you post a picture of your sweeeet wife? ;D

I would be careful to show softark a picture of my wife. He is good with everything. :D

Anyway, this wiki should also help. It creates several dataproviders in different scenarios and it also inspects an array of data received from a Dropdownlist in the view (Another use case - Child-grid in create and update actions).

http://www.yiiframework.com/wiki/323/dynamic-parent-and-child-cgridciew-on-single-view-using-ajax-to-update-child-gridview-via-controller-with-many_many-relation-after-row-in-parent-gridview-was-clicked/