php Laravel eloquent 获取关系数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41165726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:20:43  来源:igfitidea点击:

Laravel eloquent get relation count

phplaravel

提问by Vincent Decaux

I use Laravel 5.3.

我使用 Laravel 5.3。

I have 2 tables :

我有 2 张桌子:

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

And

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

I have defined my relations in my models :

我已经在我的模型中定义了我的关系:

// Article model
public function category()
{
    return $this->belongsTo(Category::class);
}

// Category model
public function children() 
{
    return $this->hasMany(Category::class, 'parent_id', 'id');
}   

Is there an easy way using Eloquent to have a list a categories with count of articles. The difficulty is that I want to group categories where id_parent = 0, i.e. I want to display only parent categories with count of articles in children.

有没有一种简单的方法使用 Eloquent 来列出一个包含文章计数的类别。困难在于我想将类别分组 where id_parent = 0,即我只想显示父类别以及子项中的文章数。

I tried something like that :

我试过这样的事情:

    $category = new \App\Models\Category();
    $categoryTable = $category->getTable();

    return $category->leftJoin('article', 'article.cat_id', '=', 'category.id')
        ->whereIn('article.cat_id', function($query)
            {
                $query->select('cat_id')
                    ->from('categories')
                    ->where('categories.parent_id', ???)
                    ->orWhere($this->tableName .'.cat_id', $id);
            })
        ->groupBy('cat_id');

But I am lost...

但是我迷路了...

回答by kapil.dev

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

你可以使用withCount(). 从 5.3 版本开始可用

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

有关雄辩访问的更多信息:https: //laravel.com/docs/5.3/eloquent-relationships

回答by Carter Fort

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 $appendsarray on the model to help illustrate it in the Tinker output.

您可以使用hasManyThrough()Eloquent 方法获取所有孩子的文章,然后将文章计数添加到一个漂亮的小 getter 中。我将 getter 添加到$appends模型上的数组中,以帮助在 Tinker 输出中进行说明。

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:

这是 Tinker 的输出:

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()方法:

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

Here's more on the has()method:

以下是该has()方法的更多信息:

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

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

And the hasManyThrough()method:

hasManyThrough()方法:

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

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

回答by Amit Gupta

Define a articles()relation in your Categorymodel as:

将模型中的articles()关系定义Category为:

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

Then you can try it as:

然后你可以尝试它:

Category::where('parent_id', 0)->withCount('articles')->get();

回答by DevK

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.

上面的查询将为您提供类别 ID 和属于该类别的所有文章的数量。

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)).

再次阅读您的问题和评论后,如果我理解正确,您想获得属于这些类别的所有文章的计数(parent_id = 0)+ 属于子类别的文章计数(那些具有 parent_id = (id of某些类别))。

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.

也就是说,我认为您最好在类别中创建一个名为 count 的列,并在每次添加新文章时对其进行更新。为了性能。

回答by Carlos_E.

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:

好吧,一些代理可能不一定分配了时间表,因此,我在调用该with()方法之前过滤了这些,如下所示:

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

Hope this helps!.

希望这可以帮助!。