CActiveRecord findAll as an array of arrays

Hi,

I’m wondering if it’s possible to have CActiveRecord::findAll() return an array of arrays rather than objects. For instance if I want just a list of ids and titles from a table to output to an html element having a list of objects seems well wrong when an array would do.

I thought of doing something like the following, but unfortunately I can’t override the private query method :( Anyone have any ideas how to accomplish this? I’m pretty much brand new to Yii so there might be some easy way to do this that I completely overlooked :\




    $list = Model::model()->as_array()->findAll();


    class Model extends GactiveRecord { blah blah blah... }


    class GActiveRecord extends CActiveRecord

    {

        protected $_as_array = false;

        

        public function as_array() {

            $this->_as_array = true;

            return $this;

        }

        

    	private function query($criteria,$all=false)

    	{

            $this->beforeFind();

            $this->applyScopes($criteria);

            $command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria);

            

            if ( $this->_as_array === true )

                return $all ? $command->queryAll() : $command->queryRow();

            else

                return $all ? $this->populateRecords($command->queryAll()) : $this->populateRecord($command->queryRow());

    	}

    }



Hi, you can use CHtml::listData() to generate needed array.


echo CHtml::activeDropDownList($model, 'category', CHtml::listData(Category::model()->findAll(), 'id', 'name'));

Also see CHtml::listOptions().

This is exactly what I want to do. It just seems, without having done any benchmarks, that it would be far less efficient with a large list of CActiveRecord objects versus arrays. Perhaps the difference is negligible and it’s a non-issue.

I think the performance difference is negligible. Still you could add special get-method to your model which uses DAO to get the data.

Simple example:




public function getList()

{


   $array = array();


   $dbCommand = Yii::app()->db->createCommand("

      SELECT `id`, `name` FROM `Category`

   ");


   $rows = $dbCommand->queryAll();


   foreach ($rows as $row)

   {

      $array[$row['id']] = $row['name'];

   }


   return $array;


}



Maybe it’s also a good idea to wrap this special get-methods into a helper so you don’t have additional methods in the model.




class FormHelper

{


   public static function getCategoryList()

   {

      ...

   }


   public static function getBirthdateYearsList()

   {

      ...

   }


   ...


}



Yea I’ve done something similar already




    public function getAllAsArray ($columns=false)

    {

        $columns = is_array($columns) ? implode(',', $columns) : '*';

        return Yii::app()->db->createCommand('SELECT '.$columns.' FROM '.self::tableName().' WHERE active = 1 ORDER BY common_name')->queryAll();

    }



But this now prevents me from using all the other fancy methods that come with CActiveRecord. I guess I’ll just have to live with objects… it’s probably not a big difference anyway.

CHtml::listData only prepares data for suitable html elements. If you need more data (like 5 fields to use from CActiveRecord), there is a simple way to run a query against CAtiveRecord automagic IF you have specified your criteria with CDbCriteria:

so, instead of


$data = Model::model()->findAll($criteria); //we get array of objects

we have


$tableSchema = Model::model()->getTableSchema();

$command = Model::model()->getCommandBuilder()->createFindCommand($tableSchema, $criteria);

$data = $command->queryAll(); //we get array of arrays