Laravel 4:在嵌套关系中,我如何急切加载并检索第一个/最后一个数据?

时间:2014-07-03 09:45:05

标签: php laravel laravel-4 eloquent

A : User,
B : Conversations,
C : Messages

我想在A的A-> B-> C关系中得到对话以及最近的消息

模型中的工作关系

User belongsToMany Conversation
Conversation belongsToMany User
Conversation hasMany Message
Message belongsTo Conversation
User hasMany Message
Message belongsTo User

**note: User and Conversation are related to a many2many relationship connected 
by a pivot table

我试过

$user->load(['conversations' => function($q)
            {
                $q->orderBy('created_at', 'desc');
                $q->with('Messages')->orderBy('created_at','desc');
            }]);

它几乎可以工作,但它没有得到最后的消息。相反,它会加载属于该对话的所有消息。

上述代码中不需要的结果

array (size=7)
  'id' => int 90
  'name' => string 'haha,hehe' (length=9)
  'created_at' => string '2014-07-03 15:04:04' (length=19)
  'updated_at' => string '2014-07-03 15:04:04' (length=19)
  'microseconds' => string '1404370893302' (length=13)
  'pivot' => 
    array (size=2)
      'user_id' => int 1
      'conversations_id' => int 90
  'messages' => 
    array (size=27)
      0 => 
        ...
      1 => 
        ...
      ...
      26 => 
          array (size=7)
             'id' => int 816
             'user_id' => int 1
             'conv_id' => int 90
             'body' => string 'test1' (length=5)
             'created_at' => string '2014-07-03 01:13:35' (length=19)
             'updated_at' => string '2014-07-03 01:13:35' (length=19)
             'microseconds' => string '1404350015499' (length=13)

预期结果

array (size=7)
      'id' => int 90
      'name' => string 'haha,hehe' (length=9)
      'created_at' => string '2014-07-03 15:04:04' (length=19)
      'updated_at' => string '2014-07-03 15:04:04' (length=19)
      'microseconds' => string '1404370893302' (length=13)
      'pivot' => 
        array (size=2)
          'user_id' => int 1
          'conversations_id' => int 90
      'messages' => 
        array (size=1)
          0 => 
             array (size=7)
               'id' => int 816
               'user_id' => int 1
               'conv_id' => int 90
               'body' => string 'test1' (length=5)
               'created_at' => string '2014-07-03 01:13:35' (length=19)
               'updated_at' => string '2014-07-03 01:13:35' (length=19)
               'microseconds' => string '1404350015499' (length=13)

2 个答案:

答案 0 :(得分:5)

当您在闭包中放置get(或first / find等)时,它再次运行查询,但忽略该查询,然后Eloquent执行该操作再次询问:

$user->load(['conversations' => function($q)
{
   $q->orderBy('created_at', 'desc');
   $q->with('Messages')->orderBy('created_at','desc')
     ->get()  // this query is executed here
     ->first();  // this calls first method on the collection
     // but those 2 lines above take no effect with the eager load models
     // because Eloquent will execute the query again in the end
}]);

这就是你如何对嵌套关系设置约束(但它不会在这里完成工作):

User::with(['conversations.messages' => function ($q) {
  $q->orderBy(...)->where(...) ...;
  // but limit(1) can't be used here
}])->get();

Limit无法使用,因为它将整个集限制为1,因此总共只会返回1条消息。也就是说,只有一个会话会在一个集合中加载单个消息。完全错误


所以使用Eloquent 实现这一目标的唯一方法就是帮助'关系:

// Conversation model
public function latestMessage()
{
  return $this->hasOne('Message')->latest();
}

// then simply:

$user->load('conversations.latestMessage');

$user->conversations->first()->latestMessage; // single Message model

答案 1 :(得分:1)

尝试使用;

User::with('conversations', 'conversions.messages')

然后你就可以用一个像<; p>这样的闭包添加你渴望的加载限制

User::with(array('conversations' => function(){}, 'conversions.messages' => function(){})

请注意,这未经过测试。