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?
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.
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.
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.
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.
[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]
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.