【问题标题】:laravel 4 eloquent eager load relation countlaravel 4 雄辩的急切负载关系计数
【发布时间】:2013-08-11 21:53:53
【问题描述】:

我有一个具有多个已定义关系的复杂模型。在此示例中,我想计算 Like 模型并创建一个名为 likes 的属性,以便可以从 REST 服务返回它。

是否可以将模型计数预先加载到动态属性中?

$beat = Post::with(
         array(
            'user',
            'likes' => function($q){
                $q->count();
            }
        ))
        ->where('id', $id)
        ->first();

【问题讨论】:

    标签: php laravel laravel-4 eloquent fluent


    【解决方案1】:

    假设您有Post->hasMany->Like 关系,并且您已将点赞关系声明为:

    class Post{
    
      public function likes(){
       return $this->hasMany('Like');
      }
    }
    

    创建一个新函数,比如likeCountRelation

    public function likeCountRelation()
    {
        $a = $this->likes();
    
        return $a->selectRaw($a->getForeignKey() . ', count(*) as count')->groupBy($a->getForeignKey());
    }
    

    现在您可以将__get() 函数重写为:

    public function __get($attribute)
    {
    
        if (array_key_exists($attribute, $this->attributes)) {
            return $this->attributes[$attribute];
        }
    
        switch ($attribute) {
    
            case 'likesCount':
                return $this->attributes[$attribute] = $this->likesCountRelation->first() ? $this->likesCountRelation->first()->count : 0;
                break;
    
            default:
                return parent::__get($attribute);
    
        }
    }
    

    或者你可以使用 getattribute 函数:

    public function getLikesCountAttribute(){
     return $this->likesCountRelation->first() ? $this->likesCountRelation->first()->count : 0;
    }
    

    只需以$post->likesCount 访问likesCount,您甚至可以像这样急切地加载它:

    $posts=Post::with('likesCountRelation')->get();
     foreach($post as $post){
      $post->likesCount;
     }
    

    NOTE: 可以使用相同的逻辑来变形许多关系。

    【讨论】:

      【解决方案2】:

      您应该使用 SQL Group By 语句才能使其正常工作。您可以像下面这样重写您的查询。

      $beat = Post::with(
               array(
                  'user',
                  'likes' => function($q) {
                      // The post_id foreign key is needed, 
                      // so Eloquent could rearrange the relationship between them
                      $q->select( array(DB::raw("count(*) as like_count"), "post_id") )
                        ->groupBy("post_id")
                  }
              ))
              ->where('id', $id)
              ->first();
      

      likes 的结果是一个包含一个元素的 Collection 对象。我假设模型PostLike之间的关系是PosthasManyLike。所以你可以像这样访问计数。

      $beat->likes->first()->like_count;
      

      我没有测试上面的代码,但它应该可以工作。

      【讨论】:

      • 您提供的代码不起作用。 like_count 未定义
      • @edi9999,它应该由 Laravel 动态定义,因为它被填充为列。看看:DB::raw("count(*) as like_count")
      • @edi9999 我正在尝试做类似的事情,但是当计数为 0 时它不起作用(因为 first() 返回 null)。为了处理这种特殊情况,我这样做了:$beat->likes->first() ? $beat->likes->first()->like_count : 0。也许你有同样的问题?
      猜你喜欢
      • 2019-09-14
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多