Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array structure returned by Yii's model

I am a Yii beginner and am running into a bit of a wall and hope someone will be able to help me get back onto track. I think this might be a fairly straight forward question to the seasoned Yii user. So here goes...

In the controller, let's say I run the following call to the model-

$variable = Post::model()->findAll();

All works fine and I pass the variable into the view. Here's where I get pretty stuck. The array that is returned in the above query is far more complex than I anticipated and I'm struggling to make sense of it. Here's a sample-

print_r($variable);

gives-

Array ( [0] => Post Object ( [_md:CActiveRecord:private] => CActiveRecordMetaData Object                             ( [tableSchema] => CMysqlTableSchema Object ( [schemaName] => [name] => tbl_post [rawName] => `tbl_post` [primaryKey] => id [sequenceName] => [foreignKeys] => Array ( ) [columns] => Array ( [id] => CMysqlColumnSchema Object ( [name] => id [rawName] => `id` [allowNull] => [dbType] => int(11) [type] => integer [defaultValue] => [size] => 11 [precision] => 11 [scale] => [isPrimaryKey] => 1 [isForeignKey] => [autoIncrement] => 1 [_e:CComponent:private] => [_m:CComponent:private] => ) [post] => CMysqlColumnSchema Object ( [name] => post [rawName] => `post` [allowNull] => [dbType] => text [type] => string [defaultValue] => [size] => [precision] => [scale] => [isPrimaryKey] => [isForeignKey] => [autoIncrement] => [_e:CComponent:private] => [_m:CComponent:private] => ) ) [_e:CComponent:private] => [_m:CComponent:private] => ) [columns] => Array ( [id] => CMysqlColumnSchema Object ( [name] => id [rawName] => `id` [allowNull] => [dbType] => int(11) [type] => integer [defaultValue] => [size] => 11 [precision] => 11 [scale] => [isPrimaryKey] => 1 [isForeignKey] => [autoIncrement] => 1 [_e:CComponent:private] => [_m:CComponent:private] => ) [post] => CMysqlColumnSchema Object ( [name] => post [rawName] => `post` [allowNull] => [dbType] => text [type] => string [defaultValue] => [size] => [precision] => [scale] => [isPrimaryKey] => [isForeignKey] => [autoIncrement] => [_e:CComponent:private] => [_m:CComponent:private] => ) ) [relations] => Array ( [responses] => CHasManyRelation Object ( [limit] => -1 [offset] => -1 [index] => [through] => [joinType] => LEFT OUTER JOIN [on] => [alias] => [with] => Array ( ) [together] => [scopes] => [name] => responses [className] => Response [foreignKey] => post_id [select] => * [condition] => [params] => Array ( ) [group] => [join] => [having] => [order] => [_e:CComponent:private] => [_m:CComponent:private] => ) ) [attributeDefaults] => Array ( ) [_model:CActiveRecordMetaData:private] => Post Object ( [_md:CActiveRecord:private] => CActiveRecordMetaData Object *RECURSION* [_new:CActiveRecord:private] => [_attributes:CActiveRecord:private] => Array ( ) [_related:CActiveRecord:private] => Array ( ) [_c:CActiveRecord:private] => [_pk:CActiveRecord:private] => [_alias:CActiveRecord:private] => t [_errors:CModel:private] => Array ( ) [_validators:CModel:private] => [_scenario:CModel:private] => [_e:CComponent:private] => [_m:CComponent:private] => ) ) [_new:CActiveRecord:private] => [_attributes:CActiveRecord:private] => Array ( [id] => 1 [post] => User Post ) [_related:CActiveRecord:private] => Array ( ) [_c:CActiveRecord:private] => [_pk:CActiveRecord:private] => 1 [_alias:CActiveRecord:private] => t [_errors:CModel:private] => Array ( ) [_validators:CModel:private] => [_scenario:CModel:private] => update [_e:CComponent:private] => [_m:CComponent:private] => ) )

[sorry if there's an easier way to show this array, I'm not aware of it]

Can anyone explain to me why the model returns such a complex array? It doesn't seem to matter what tables or columns or relations are used in your application, they all seem to me to return this format.

Also, can someone explain the structure to me so that I can isolate the variables that I want to recover?

Many thanks in advance,

Nick

like image 956
goose Avatar asked Sep 30 '12 19:09

goose


2 Answers

Better print_r

To get a better print_r output in yii, you can use the CVarDumper class' dump() or dumpAsString() methods. They also provide a parameter $highlight which will help you make sense of the output, by properly formatting the output, and adding indentation to it. Example:

CVarDumper::dump($variables,10,true);
// 10 is the default depth, and passing true will enable highlighting

Why and what structure?

As already mentioned in the other answers findAll() returns an array of CActiveRecord objects, so $variables is an array of objects, and $variables[0] is the first Post object. Yii's CActiveRecord has a host of properties which are objects, for instance a CActiveRecordMetaData object, which in turn has a CDbTableSchema object (and you have it's subclass the CMysqlTableSchema, which means you are using mysql). The print_r is simply printing out these objects, which are nothing but properties of the main CActiveRecord object. In addition to these objects the attributes property(which is an array) of a CActiveRecord holds your actual attribute values, so somewhere in the output you'll also see an array like this:

[CActiveRecord:_attributes] => array
(
    'attributeName' => 'attributeValue'
    'anotherAttributeName' => 'anotherAttributeValue'
    'someAttributeName' => 'someAttributeValue'
    ...
)

Those are your attribute values.


How to access?

To access a model's properties we can use both object property access, and associative array access(Probably because CActiveRecord's parent class CModel implements php's ArrayAccess interface). Example:

$variables[0]->attributeName;
$variables[0]['attributeName'];

And since yii uses and overrides the __get php magic method we can do:

$variables[0]->attributeName;
// instead of 
$variables[0]->attributes['attributeName'];

And of course you can iterate over the array of Post objects using foreach() as already shown in another answer here:

foreach($variables as $aPost){
    echo $aPost->attributeName;
    echo $aPost['attributeName'];
    echo $aPost->attributes['attributeName'];
}

To access relations, just use the relation name:

$variables[0]->relationName->attributeOfRelatedTable;
$variables[0]['relationName']->attributeOfRelatedTable;
$variables[0]['relationName']['attributeOfRelatedTable'];

If your relation is HAS_MANY, then of course the related models will also be returned as an array:

$variables[0]->relationName[0]->attributeOfRelatedTable;
$variables[0]['relationName'][0]->attributeOfRelatedTable;
$variables[0]['relationName'][0]['attributeOfRelatedTable'];
$variables[0]->relationName[0]['attributeOfRelatedTable'];

And again you can iterate over the relations array incase of HAS_MANY relations.

Edit: example for has_many iteration:

foreach($variables as $aPost) { // get each post one by one
    echo $aPost->someAttribute; // or $aPost['someAttribute']
    foreach($aPost->relationName as $aComment) { // say we get each comment of each post
        // or could have done $aPost['relationName'] as $aComment
        echo $aComment->commentAttribute; // or $aComment['commentAttribute']
    }
}
like image 192
bool.dev Avatar answered Oct 23 '22 21:10

bool.dev


findall returns an array of active records for your model see here

Once you have that you can access all the columns in each record returned like so

$results = Post::model()->findAll();
foreach($results AS $model) 
{
    echo $model->somecolumnname;
    echo $model->someothercolumnname;
}

So you don't have to concern yourself too much with all that detail under the hood as you can just use the abstraction directly.

like image 2
sdjuan Avatar answered Oct 23 '22 19:10

sdjuan