Reputation: 5567
So I'm getting a bit lost with CActiveRecord in Yii.
Let's say I have the following simple models:
So Post HAS_MANY Comment, I think the relationship should be fairly obvious from that description.
What if I want to get all comments, and then within that get a specific comment for something? Like I want to display a list of comments for a post, but show the content of just one of them(by PK).
So I have:
$this->post = Post::model()->with('comments')->findByPk( $pid );
// this next line is an extra DB Query, right?
$this->comment = Comment::model()->findByPk( $cid );
But I want something like:
$this->post = Post::model()->with('comments')->findByPk( $pid );
// this is not valid code because the comments is an array
$this->comment = $this->post->comments->findByPk( $cid ); // <---
Do I just have to wrap that in a loop myself to implement findByPk the second time?
My second question is, can I do something like the following?
$this->post = Post::model()->with('comments')->findByPk( $pid );
$this->comment = Comment::model()->findByPk( $cid );
// Get the PK of the next and previous comments from the $cid comment
// again, not valid code
$this->next = $this->post->NextComment($this->comment);
$this->prev = $this->post->PreviousComment($this->comment);
Or do I again need to wrap my own loop over the comments?
I'm really just trying to take advantage of what Yii has to offer before I write extra code. The documentation always assumes you always want all of the relational data, it doesn't specify how to pick parts of the relational data.
Upvotes: 3
Views: 5888
Reputation: 1289
Answer for the first question is
$post = Post::model()->with('comments')->find('t.id = :post_id AND comments.id = :comment_id', array(
':post_id' => $somePostId,
':comment_id' => $someCommentId,
));
or
$post = Post::model()->findByPk($somePostId);
$comments = $post->comments(array(
'condition' => 'comments.id = :comment_id',
'params' => array(':comment_id' => $someCommentId),
));
The second question: what do you mean by "next" and "previous" comment? Next to what? To id or to create_time?
You can do for it something like this (for previous by create_time):
$post = Post::model()->findByPk($somePostId);
$comment = Comment::model()->findByPk(someCommentId);
$previousComment = $post->comments(array(
'condition' => 'comments.create_time < :comment_create_time',
'params' => array(':comment_create_time' => $comment->create_time),
'limit' => 1,
));
You can get more info about this topic here and also from official class reference for CActiveRecord.find()
Update
If you want get all comments from db and than get one by id you can do it this way:
$post->comments is just an array. So you can loop through it and get yours as you described in the topic.
But also you can add a new method to Post model class (not comments because it's an array) like "findCommentById":
public function findCommentById($id)
{
foreach ($this->comments as $comment)
if ($comment->id == $id)
return $comment;
return null;
}
Upvotes: 1