Converting between CActiveDataProvider and CSqlDataProvider and vice-versa

Hi, there!

Let’s say, that I need all the functionality of CActiveRecord (especially ability of using virtual model’s attributes by using own getters and setters, but not only), but in the same time I don’t want to use internal AR method to query database. But rather I would like to use own SQL query and it’s result.

I figured out that, both data providers provide setData and getData function. So my first thought was to use something like this (my model’s search function):


$sqlDataProvider = new CSqlDataProvider($querySQL, array

(

    	'totalItemCount'=>$count,

    	'pagination'=>array('pageSize'=>$pageSize)

));


$arDataProvider = new CActiveDataProvider(get_class($this), array

(

    	'pagination'=>array('pageSize'=>$pageSize)

));


$arDataProvider->setData($sqlDataProvider->getData());

What do you think about such idea?

Is it some kind of madness or may work? And most important - how to prevent CActiveDataProvider from executing the query?

The reason for me looking such, maybe strange solution, is that CActiveRecord itself would be very slow in comparison to just using DAO and pure SQL query. There reasons, while it is much slower are partly beyond Yii and partly are about complexity of SQL query. So, I would be very happy to receive advices, if my idea is correct or how to get expected results? Let’s don’t discuss if ActiveRecord will or will not be slower here or if forcing myself to use SQLDataProvider istead of AR are correct. Let’s just assume that they are.

good thought :rolleyes: , but i don’t think it will work well . especially for the implement reason ,you can read the CActiveDataProvider::fetchData(),and calculateTotalItemCount() … which are different to the CSqlDataProvider; you should also consider the ordering , filtering , pagination etc .

but if you want use the power of CActiveRecord ,just new it in the view file and initiate it with the sql execution result :




$ar = new MyModel; 

$ar->populateRecord($data,true); //here the $data is row of some select querying result


//here you go ... <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/biggrin.gif' class='bbc_emoticon' alt=':D' /> 

$ar->someRelationField;

$ar->someMethod();




Yeap! I’ve already come out with the same conclusion, but on the other hand, your idea with populateRecord seems to be GREAT! So, thanks and +1 for this!

On, second thought… Good question, why this function does not work? :expressionless:

This is my data array (result of SQL query):


$data = Array

(

	[ID] => 162

	[TYPA] => W

	[LOGN] => TREJDER

	[IMIE] => Tomasz

	[NAZW] => Trejderowski

)

I feed my model like this:


$data = $this->getUser($id);


$model = new Users;

$model->populateRecord($data, FALSE);

If I then print out it’s contents:


echo('<pre>$model = '.print_r($model, TRUE).'</pre>');

or use it in any other way, I clearly see, that it is empty.

But if I feed it manually like this:


$model->ID = $data['ID'];

$model->TYPA = $data['TYPA'];

$model->LOGN = $data['LOGN'];

$model->IMIE = $data['IMIE'];

$model->NAZW = $data['NAZW'];

that is, I do, what populateRecord should do, I’m getting everything OK.

What am I missing?

CActiveRecord::populateRecord() returns a new model instance populated with the given data. The instance it was called on won’t be changed.

Thank you very much. Here goes, what means "read docs with understanding"! :]