Cactiverecord vs cactivedataprovider

I am a bit confused with yii’s data access features. I understand that yii returns CActiveRecords in object format, while CActiveDataProvider returns results in array format. What I find unclear is when to use active record vs data provider. It seems all of yii’s built-in views and widgets for displaying results e.g. CListView or CGridView, require a DataProvider to work. In which case, why would I ever want to use CActiveRecord to load results for display? If fact, I cannot think of any situation where I would use CActiveRecord instead of CActiveDataProvider. Why is CActiveRecord class even provided as an option in Yii? When would i use it instead of CActiveDataProvider?

Am I missing something? Can someone enlighten me?

AR find() methods and HAS_ONE relationships return one AR object.

AR findAll() methods, HAS_MANY and MANY_MANY relationships return an array of AR objects.

CActiveDataProvider uses AR. The getData() method of the dataprovider returns an array of AR objects.

The zii widgets expects a dataprovider instance. No doubt there are tasks that don’t need a dataprovider (no pagination or sort) or can’t/shouldn’t use a dataprovider. One example of AR usage is to populate dropdownlists/checkboxlists/radiobuttonlists.

There are even situations when we may want to use DAO or Query Builder. Read more in The Definitive Guide to Yii.

/Tommy

Thanks Tri.

I am aware of active record’s find/findAll methods, but they’re not all that helpful, as they don’t work with CListView, CDetailView, or the other zii widgets. I am also a big fan of Query Builder, and find it easy to use and powerful enough to construct all manners of SQL queries. This is really my issue with Yii - there are so many ways to generate SQL and query data that I am suffering from choice fatigue and really don’t know which approach to use in which situation. Even for a page that does not require pagination, e.g. a product details page, I would use data provider instance instead of CActiveRecord, as CDetailView requires a data provider. I still don’t understand when I would need to use active record vs the data provider.

I simply don’t get that you don’t get it…

What are you using then?

Instead of Models, I mean?

Choice is good - which is why I personally love Yii - but day to day Yii programming is based on CActiveRecord models, controllers and views.

From the API docs:

There is a CArrayDataProvider too, leading me to believe that IDataProvider is something which you can pass to various things, such as several Zii widgets which takes data.

You could probably invent other forms of dataproviders and instantly use them with Zii widgets and other objects which takes an IDataProvider.

For completeness:

Taken from IDataProvider API doc page.

If you find yourself wondering about something Yii-ish, why not take the time and browse the docs? :)

CActiveDataProvider itself uses CActiveRecord::findAll() to retrieve records. In fact, it’s just a wrapper for CActiveRecord that performs some additional sorting/pagination magic. Use CActiveDataProvider when you need this extra features.

I don’t think CDetailView requires a dataprovider. It displays a model instance returned by a finder method of CActiveRecord.

Main purpose of Active Record is not to generate complex sql queries but to encapsulate data and business logic associated with the data. Use Query Builder (and/or CSqlDataProvider) when you want to display raw data from database.

But imagine, for example, a shopping cart in a webshop:

It’s easy to retrieve cart items from the database even with plain sql, but then lots of additional logic needs to be performed. Totals, various discounts, VAT, postage price, etc, all has to be calculated. Where to put this logic? A good answer may be the ShoppingCart model.

I’m also wondering why we have to build a dataprovider object when we could simply supply an array of ARs

ex:

I’d like to do

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

	'dataProvider'=>[b][color="#0000FF"]$post->comments[/color][/b],

[color="#FF0000"]Fatal error: Call to a member function getData() on a non-object in X:\X_Dev\perfony\perfony\yii-1.1.8.r3324\framework\zii\widgets\CBaseListView.php on line 105[/color]

but This wont work , or am I doing it wrong ?

and not have to do :

$dataProvider=new CActiveDataProvider(‘Comments’, array(

            'criteria'=>$criteria,


    ));


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


	'dataProvider'=>[b][color="#0000FF"]$dataProvider[/color][/b],

Here’s my try on making the difference more clear. It’s a nice example for what OOP is about.

It all depends on your use case:

1. Simple List - No pagination, no sorting

Then you don’t need a CListView/CGridView- just use a findAll() method. You get a simple array and can use foreach in your view to loop over the result.

[b]

[/b]

2. List with pagination or sorting

You don’t want to repeat yourself, so you use a CListView/CGridView. Both help to automate pagination/sorting. To do their job, they ask questions like: “Can you please give me an Array of 25 objects for page 5, ordered by ID?”. The questions are always similar (or generic). Hence there’s a generic object that can answer all these kind of questions: CDataProvider. It is like a clever list, that will automatically provide you with the right array of objects.

And since there can be different sources for your data, they come in different flavours: CActiveDataProvider(if you use AR), CSqlDataProvider (if you use raw SQL) and even CArrayDataProvider (if all you have is a long list of data). For the list views each of them behaves the same - they wont feel any difference.

hello… i was wondering how to use query builder… where should i place it? can i also have some examples… Thank you very much…