Laravel eloquent get relation count

前端 未结 5 2035
温柔的废话
温柔的废话 2021-02-05 00:29

I use Laravel 5.3.

I have 2 tables :

Articles
---------
id
cat_id
title

And

Category
---------
id
parent_id
title


        
相关标签:
5条回答
  • 2021-02-05 01:01

    Define a articles() relation in your Category model as:

    public function articles() 
    {
        return $this->hasMany(Article::class, 'cat_id');
    }
    

    Then you can try it as:

    Category::where('parent_id', 0)->withCount('articles')->get();
    
    0 讨论(0)
  • 2021-02-05 01:03

    This should work:

    $category
    ->where('categories.parent_id', 0)
    ->leftJoin('article', 'article.cat_id', '=', 'categories.id')
    ->select('categories.id', \DB::raw('COUNT(article.id)'))
    ->groupBy('categories.id')
    ->get();
    

    The above query will get you category IDs and count of all articles that belong to the category.

    After reading your question and comments again, if I understand correctly you want to get the count of all articles that belong to those categories (with parent_id = 0) + the count of articles that belong to sub categories (those with parent_id = (id of some category)).

    Now I have no way of testing this easily, but I think something along these lines should work for that.

    $category
    ->where('categories.parent_id', 0)
    ->leftJoin('article', 'article.cat_id', '=', 'categories.id')
    ->leftJoin('categories as c2', 'c2.parent_id', '=', 'categories.id')
    ->leftJoin('article as a2', 'a2.cat_id', '=', 'c2.id')
    ->select('categories.id', \DB::raw('(COUNT(article.id)) + (COUNT(a2.id)) as count'))
    ->groupBy('categories.id')
    ->get();
    

    That beign said, I think you're better of having a column named count in categories and update it each time a new article gets added. For performance.

    0 讨论(0)
  • 2021-02-05 01:11

    I am sure somebody is still going through this, I was able to solve it the following way, suppose I have an Agent model and a Schedule model, i.e. one agent may have many schedules:

    class Schedule extends Model {
      public function agent() {
        return $this->belongsTo(Agent::class, 'agent_id');
      }
    }
    
    class Agent extends Model {
      public function user(){
        return $this->belongsTo(User::class);
      }
    
      public function schedules(){
        return $this->hasMany(Schedule::class);
      }
    }
    

    Well some agents may not necessarily have schedules assigned, thus, I filtered those before calling the with() method, like this:

    $agents = Agents::whereIn(
        'id', 
        Schedule::distinct()->pluck('agent_id')
    )->with('schedules')->get();
    

    Hope this helps!.

    0 讨论(0)
  • 2021-02-05 01:19

    You can use the hasManyThrough() Eloquent method to fetch all of the childrens' Articles, then add the article counts together in a nice little getter. I added the getter to the $appends array on the model to help illustrate it in the Tinker output.

    class Category extends Model
    {
    
        protected $appends = [
            'articleCount'
        ];
    
        public function articles()
        {
            return $this->hasMany(Article::class);
        }
    
        public function children()
        {
            return $this->hasMany(Category::class, 'parent_id');
        }
    
        public function childrenArticles()
        {
            return $this->hasManyThrough(Article::class, Category::class, 'parent_id');
        }
    
        public function getArticleCountAttribute()
        {
            return $this->articles()->count() + $this->childrenArticles()->count();
        }
    }
    

    Here's the Tinker output:

    Psy Shell v0.8.0 (PHP 7.0.6 — cli) by Justin Hileman
    >>> $cat = App\Category::first();
    => App\Category {#677
         id: "1",
         name: "Cooking",
         parent_id: null,
         created_at: "2016-12-15 18:31:57",
         updated_at: "2016-12-15 18:31:57",
       }
    >>> $cat->toArray();
    => [
         "id" => 1,
         "name" => "Cooking",
         "parent_id" => null,
         "created_at" => "2016-12-15 18:31:57",
         "updated_at" => "2016-12-15 18:31:57",
         "articleCount" => 79,
       ]
    >>> 
    

    If you want to restrict your Category query to ones that have children that have articles, you could do that using the has() method:

    Category::has('children.articles')->get();
    

    Here's more on the has() method:

    https://laravel.com/docs/5.3/eloquent-relationships#querying-relationship-existence

    And the hasManyThrough() method:

    https://laravel.com/docs/5.3/eloquent-relationships#has-many-through

    0 讨论(0)
  • 2021-02-05 01:20

    you can use withCount(). It is available from 5.3 version

    for more info about eloquent visit : https://laravel.com/docs/5.3/eloquent-relationships

    0 讨论(0)
提交回复
热议问题