Laravel 过滤有很多结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25474917/
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-09-14 09:59:19  来源:igfitidea点击:

Laravel filtering hasMany results

phpdatabaselaraveleloquent

提问by taekni

I have three tables - Campaigns, Actions and Activists. A Campaign has many Actions, and an Action belongs to both an Activist and a Campaign.

我有三张表 - 活动、行动和活动家。一个运动有许多动作,一个动作同时属于一个行动者和一个运动。

Each action has a client_id (from the client_id of the campaign it belongs to), so when a client views a list of activists, they should only see those who have taken an action on one of their campaigns.

每个动作都有一个 client_id(来自它所属活动的 client_id),因此当客户查看活动家列表时,他们应该只看到那些对其中一个活动采取了行动的人。

Likewise, when viewing an individual activist, they should only see those actions related to their campaigns.

同样,在查看个人活动家时,他们应该只看到与他们的活动相关的那些行为。

Models

楷模

Campaign.php

活动.php

public function actions()
{
    return $this->hasMany('Action');
}

Action.php

动作.php

public function campaign()
{
    return $this->belongsTo('Campaign', 'campaign_id');
}

public function activist()
{
    return $this->belongsTo('Activist', 'activist_id');
}

Activists.php

活动家.php

public function actions()
{
    return $this->hasMany('Action');
}

Controllers

控制器

ActivistsController.php

ActivistsController.php

public function index()
{
    $activists = Activist::with('actions')->whereHas('actions', function($q) {
        $user = Sentry::getUser();
        $q->where('client_id', $user->client_id);
    }))->get();

    foreach ($activists as $activist)
    {
         $activist->total = $activist->actions()->count();
    }
}

public function getActivist($id)
{
    $activist = Activist::with('actions')->whereHas('actions', function($q) {
        $user = Sentry::getUser();
        $q->where('client_id', $user->client_id);
    })->find($id);

    $activist->total = $activist->actions()->count();
}

I'm seeing the following:

我看到以下内容:

On the /activists page, I'm correctly seeing only those activists who have taken an action related to my client_id, but also every action they've taken. Likewise, count() returns a full count of all the activists' actions.

在 /activists 页面上,我正确地只看到那些采取了与我的 client_id 相关的行动的积极分子,但也看到了他们采取的每一个行动。同样,count() 返回所有活动家行动的完整计数。

On the /activists/{id} page, it correctly returns null if the activist hasn't taken any actions related to my client_id, but where they have, I again see all of their actions and a full count.

在 /activists/{id} 页面上,如果激进主义者没有采取任何与我的 client_id 相关的行动,它会正确返回 null,但在他们采取的地方,我再次看到他们的所有行动和完整计数。

AFL. There's something blinding obvious I'm missing, right?

美联航。我遗漏了一些明显的东西,对吧?

Thanks.

谢谢。

[edit] Updated to add:

[编辑] 更新添加:

Using the client_id filter on both with and whereHas rectifies the 'all actions appearing regardless' issue, but the count issue remains (and I'm not sure this is remotely the right way to improve this):

在 with 和 whereHas 上使用 client_id 过滤器可以纠正“所有操作都出现不管”问题,但计数问题仍然存在(我不确定这是否是改善此问题的正确方法):

ActivistController.php

ActivistController.php

public function index()
{
    $filter = function($q) {
        $user = Sentry::getUser();
        $q->where('client_id', $user->client_id);
    };

    $activists = Activist::with(array('actions' => $filter))
    ->whereHas('actions', $filter)
    ->get();
}

public function getActivist($id)
{
    $filter = function($q) {
            $user = Sentry::getUser();
            $q->where('client_id', $user->client_id);
    };

    $activist = Activist::with(array('actions' => $filter))
    ->whereHas('actions', $filter)
    ->find($id);
}

回答by taekni

I've solved this now, but for reference:

我现在已经解决了这个问题,但供参考:

$activist->actions()->count()

This, obviously in hindsight, ignores any of the prior queries and simply counts data returned from the actions() method as defined in the activist model.

事后看来,这显然会忽略任何先前的查询,并简单地计算从活动模型中定义的 actions() 方法返回的数据。

I should have provided an alternate method in the model that includes the appropriate where function, like so:

我应该在模型中提供一种替代方法,其中包括适当的 where 函数,如下所示:

public function actionsClient($id)
{
    return $this->hasMany('Action')->where('client_id', $id);
}

Meaning the count could then be invoked with:

这意味着可以通过以下方式调用计数:

$activist->total = $activist->actionsClient($id)->count();

for a single campaign and

对于单个广告系列和

foreach ($activists as $activist)
{
    $activist->total = $activist->actionsClient($activist->id)->count();
}

on the index. I'd previously tried this, but as described here - How to access model hasMany Relation with where condition?- relations must be described in camelCase (actions_client > actionsClient).

指数上。我以前试过这个,但如这里所述 -如何访问模型 hasMany Relation with where 条件?- 关系必须以驼峰命名(actions_client > actionsClient)来描述。

回答by Sinan Eldem

In my usage this worked for me:

在我的使用中,这对我有用:

$clients = Profile::select('id', 'name')->orderBy('initial')->whereHas('type', function ($query) {
    $query->where('slug', 'client');
})->office()->pluck('name', 'id');

回答by GaimZz

You already have the instance of $activist eager loading their actions, meaning you already know the actions of the activist beacause they are already in the instance, so why call actions() again instead of just doing this:

你已经有 $activist 急切加载他们的动作的实例,这意味着你已经知道激进主义者的动作,因为他们已经在实例中,那么为什么要再次调用 actions() 而不是这样做:

$activist->actions->count()