Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relational fixtures in Yii

Tags:

php

fixtures

yii

How do I set up fixtures with relationships in Yii? For example, with posts can have comments, how do I refer to the post id in a fixture for creating comments?

Post fixture:

return array(
  'post1'=>array(
    'title'=>'My title',
    'body'=>'My text',
  ), 
  ...

Comment fixture:

return array(
  'comment1'=>array(
    'text'=>'Comment text...',
    'post_id'=> ???
  ), 
like image 592
Matt Hampel Avatar asked Jun 14 '11 21:06

Matt Hampel


People also ask

What is ORM in Yii?

The ActiveRecord class in Yii provides an object oriented interface (aka ORM) for accessing database stored data. Similar structures can be found in most modern frameworks like Laravel, CodeIgniter, Smyfony and Ruby.

What is active record in Yii?

Active Record automatically maintains the list of dirty attributes. It does so by maintaining an older version of the attribute values and comparing them with the latest one. You can call yii\db\ActiveRecord::getDirtyAttributes() to get the attributes that are currently dirty.

What is Yii ::$ app?

Applications are objects that govern the overall structure and lifecycle of Yii application systems. Each Yii application system contains a single application object which is created in the entry script and is globally accessible through the expression \Yii::$app .


3 Answers

I don't know whether there is a dynamic way to do that, but the following should work:

Post fixture:

return array(
  'post1' => array(
    'id' => 1 
    'title' => 'My title',
    'body' => 'My text',
), 

Comment fixture:

return array(
  'comment1' => array(
    'text' => 'Comment text...',
    'post_id' => 1
),
like image 85
Wytse Avatar answered Sep 29 '22 08:09

Wytse


As far as I've worked out, you can use init scripts instead of classical fixtures. The Yii documentation reads:

It is also possible that we do not like the default way of resetting a table, i.e., truncating it and inserting it with the fixture data. If this is the case, we can write an initialization script for the specific fixture file. The script must be named as the table name suffixed with .init.php. For example, the initialization script for the Post table would be Post.init.php. When CDbFixtureManager sees this script, it will execute this script instead of using the default way to reset the table.

So in your case, instead of having protected/tests/fixtures/Comment.php, you would have protected/tests/fixtures/Comment.init.php which does this:

// the $this variable refers to the CBdFixtureManager instance
$this->truncateTable($tableName);
$post = $this->getRecord('Post','post1'); // get dependent fixture

// define new fixture
$commentAttributes = array(
  'text' => 'Comment text...',
  'post_id' => $post->id
);
$comment = new Comment;
$comment->setAttributes($commentAttributes);
if(!$comment->save()) throw new CException('Unable to save fixture');

// add new row primary key
$pk = Comment::model()->getTableSchema()->primaryKey;
if(is_string($pk))
  $commentAttributes[$pk] = $comment->$pk;
elseif(is_array($pk))
  foreach($pk as $key)
    $commentAttributes[$key] = $comment->$key;

$this->_rows['Comment']['comment1'] = $commentAttributes;
$this->_records['Comment']['comment1'] = 'Comment';

Although I realize it's a very late reply, that should fix your problem. Since I got here googling, I was hoping I could help someone else who needs this info.

like image 36
tetele Avatar answered Sep 29 '22 09:09

tetele


I know it's already answered but I think this is a better answer. Yes, you can use dynamic fields for relations:

Post fixture:

return array(
  'post1' => array(
    'title' => 'My title',
    'body' => 'My text',
), 

Comment fixture:

return array(
  'comment1' => array(
    'text' => 'Comment text...',
    'post_id' => $this->getRecord('post', 'post1')->id
),

PostTest.php

public $fixtures=array(
    'post'=>'Post',
    ...
);

Yii docs CDbFixtureManager

like image 40
kcsoft Avatar answered Sep 29 '22 08:09

kcsoft