简体   繁体   中英

Yii Framework How to Access Relational ActiveRecord by ID and get next?

So I'm getting a bit lost with CActiveRecord in Yii.

Let's say I have the following simple models:

  • Post
    • id
    • content
  • Comment
    • id
    • content
    • post_id

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM