Laravel 4:在嵌套关系中,我如何热切加载和检索第一个/最后一个数据? [英] Laravel 4 : In nested relationship, how do I eager load and retrieve just the first/last data?

查看:126
本文介绍了Laravel 4:在嵌套关系中,我如何热切加载和检索第一个/最后一个数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

A:用户,
B:对话,
C:消息

我想与A中的A-> B-> C关系得到对话与最新消息



模型中的工作关系

 用户属于多对话
对话belongsToMany用户
对话有多个消息
消息属于对话
用户hasMany消息
消息属于用户

**注意:用户和对话与many2many有关关系连接
由枢轴表

我尝试了

  $ 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'=>字符串'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)


解决方案

获得(或首先 / 找到等)在闭包中,它再次运行查询,但是该查询被忽略,然后Eloquent再次执行该查询:

  $ user-> load(['conversations'=> function($ q)
{
$ q-> orderBy('created_at','desc');
$ q- > with('Messages') - > orderBy('created_at','desc')
- > get()//此查询在这里执行
- > first(); / /这调用第一个方法收集
//但上述2行对于eager负载模型
//不起作用,因为Eloquent将在最后执行查询
}]) ;

这是你如何对嵌套关系进行约束(但不会在这里工作):

  User :: with(['conversations.messages'=> function ){
$ q-> orderBy(...) - > where(...)...;
//但限制(1)不能在这里使用
}]) - > get();

限制不能使用,因为它将整个设置限制为1,因此总共只返回1个消息。也就是说,只有1个对话将在一个集合中加载单个消息。完全错误






所以唯一的这个帮助者关系的方式可以实现这一点:

  //对话模型
public function latestMessage()
{
return $ this-> hasOne('Message') - > latest();
}

//然后简单地:

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

$ user-> conversations-> first() - > latestMessage; //单个消息模型


A : User,
B : Conversations,
C : Messages

I want to get the conversation together with it's most recent message in an A->B->C relationship from A.

Working relationships in model

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

I've tried

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

It nearly worked but it doesn't get the last message. Instead, it loads all of the messages belonging to that conversation.

Unwanted result from above code

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)

Expected result

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)

解决方案

When you put get (or first/find etc for that matter) in the closure it runs the query once more, but that query is ignored, and then Eloquent executes that query again:

$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
}]);

This is how you put constraints on the nested relation (but it won't do the job here):

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

Limit can't be used because it limits the whole set to 1, so there will be only 1 message returned in total. That said, only 1 conversation will have loaded single message in a collection.. Totally wrong


So the only way to achieve this with Eloquent is this 'helper' relation:

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

// then simply:

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

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

这篇关于Laravel 4:在嵌套关系中,我如何热切加载和检索第一个/最后一个数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆