ActiveRecord vs SQL

I see that when we are using ActiveRecord, we will access the result using -> because the active record itself is an object. While when we are using sql (query builder or manually write) it will return in array, so when I want to access certain column value I need to use $data[‘column_name’];

I just wonder why won’t make the queryXX() function to return in object instead array. By this way I think it will more consistence. For example in CActiveDataProvider vs CSqlDataProvider in the value I need to differentiate the code like this

CActiveDataProvider


'columns'=>array(

		array(

			'value'=>'$data->firstname.$data->lastname',

			'header'=>'full_name',


		),



[b]

CSqlDataProvider[/b]


'columns'=>array(

		array(

			'value'=>'$data["firstname"].$data["lastname"]',

			'header'=>'full_name',


		),



which ultimately make me have to write two cgridview…

I just hope at least the cdbcommand has some query functions to return object

CActiveDataProvider can return objects because you have defined a model… it returns objects of the model type… and if you do a print_r($model) you will see that there is more information than only the data… that’s why AR objects needs more memory…

on the other hand if you give a sql command like "select * from table"… Yii does not know what type of object you would like so it cannot return an object… and instead it returns arrays… that holds just the data… (less memory needed)

I think we simply call by $data[‘field’], because CSqlDataProvider or CActiveDataProvider, can use it.

Yes, active record hold more data than Sql command do. But what I hope is, beside returning array, isn’t it also possible to return in object type, some kind like mysql_fetch_assoc() vs mysql_fetch_object()? By using mysql_fetch_object() I can access the value of the query by using ->

And of course it won’t hold any values other than the row itself. I believe PHP array and object don’t have too much differences in performance. But I personally prefer accessing value by using -> rather than [] because of the sake of easy in maintenance and readability.

You can always cast an array as object like


$object=(object)$array;

I see…

And can this apply to CListView or CGridView when we are using CSqlDataProvider

I did not try it, yet… make a test… and let us know…


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

	'id'=>'student-grid',

	'dataProvider'=>$dataProvider,//this is CSqlDataProvider

	'filter'=>$model,

	'columns'=>array(

		array(

			'value'=>'$data["address"]',

			'header'=>'test',

		),

	),

)); ?>

I tried to put (object), but seems like there is no place I can put to convert the $data (in the value) from array to object. So I think it can’t be help. Must use array to access the data (except CActiveRecord who use -> ) inside the “column” parameter.

I don’t have time to test it, and not sure if it’s a good practice… but have you tried


'dataProvider'=>(object)$dataProvider

or in the code where you assign the value to $dataprovider to do something like


$dataprovider = (object) ...your code...

Hi mdomba,

Yes I understand. I’ve tested the first one, but well it can’t because sqldataprovider itself is an object, there is no point to type-casting it to object.

I guess it is CBaseListView that calling the IDataProvider and setting the $data according to the dataprovider type. The property $data in the CBaseListView is varying according to the dataProvider type. But I see that from all the dataprovider only CActiveDataProvider that set the $data in object while others set it become array. This is only my guess, because I don’t quite understand the logic behind the codes.

Yes, I did not think of that…

The method that returns the actual data in array form is fetchData() - http://www.yiiframework.com/doc/api/1.1/CSqlDataProvider#fetchData-detail

It just returns the result of "findAll()"

So to make it an object by using casting you would need to create a custom sql dataprovider that extends from the default one and then your fetchData would be something like


return (object)parent::fetchData();

NOTE: not tested, and not really sure if it would work… it’s just an idea

Yeah, I think that’s the only way. But I do hope for the next release at least we have a consistencies between array and object result. So the widget can be more reusable…

Anyway, thank you for suggestion.

CActiveRecord implements ArrayAccess interface, so you can write reusable code by using array syntax everywhere. I know that it isn’t the solution you are looking for, but can be a good workaround.