Laravel 过滤有很多结果

Posted

技术标签:

【中文标题】Laravel 过滤有很多结果【英文标题】:Laravel filtering hasMany results 【发布时间】:2014-10-17 22:54:45 【问题描述】:

我有三个表格 - 活动、行动和活动家。一个 Campaign 有很多 Action,一个 Action 既属于 Activist 又属于 Campaign。

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

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

模型

Campaign.php

public function actions()

    return $this->hasMany('Action');

Action.php

public function campaign()

    return $this->belongsTo('Campaign', 'campaign_id');


public function activist()

    return $this->belongsTo('Activist', 'activist_id');

Activists.php

public function actions()

    return $this->hasMany('Action');

控制器

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();

我看到以下内容:

在 /activists 页面上,我正确地只看到了那些已采取与我的 client_id 相关的操作的活动家,而且还看到了他们已采取的每项操作。同样,count() 返回所有活动家行动的完整计数。

在 /activists/id 页面上,如果活动家没有采取任何与我的 client_id 相关的操作,它会正确返回 null,但在他们有的地方,我再次看到他们的所有操作和完整计数。

美国橄榄球联盟。我错过了一些明显的东西,对吧?

谢谢。

[编辑] 更新添加:

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

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

【问题讨论】:

也许你可以试试这个github.com/fico7489/laravel-eloquent-join 【参考方案1】:

我现在已经解决了,但供参考:

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

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

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

public function actionsClient($id)

    return $this->hasMany('Action')->where('client_id', $id);

意思是计数可以被调用:

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

对于单个广告系列和

foreach ($activists as $activist)

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

在索引上。我之前尝试过这个,但正如这里所描述的 - How to access model hasMany Relation with where condition? - 必须在 camelCase (actions_client > actionsClient) 中描述关系。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

您已经拥有 $activist 的实例,急切地加载他们的动作,这意味着您已经知道激进分子的动作,因为它们已经在实例中,所以为什么要再次调用 actions() 而不是这样做:

$activist->actions->count()

【讨论】:

以上是关于Laravel 过滤有很多结果的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 过滤嵌套关系

使用 laravel 范围避免歧义

Laravel Eloquent Postgresql Select with Case,然后按 Case 结果过滤

Vue JS 对分页 Laravel 结果的实时客户端搜索过滤器

Laravel:高级搜索表单查询

Laravel 复选框过滤器 ajax