【问题标题】:Laravel count results in controller or viewLaravel 计数结果在控制器或视图中
【发布时间】:2014-06-18 07:38:59
【问题描述】:

逻辑:一个用户有很多积分。

控制器:

public function getAdminAccount()
{
    $company = User::find(Auth::user()->id)
                ->companies()
                ->with('users.credits')
                ->first();
    $this->layout->content = View::make('agents.admin.account',
                array('company' => $company));
}

我的控制器函数正在返回我需要的 JSON 数据中的正确数据,但是,我想根据 user_id 计算结果,最好是在它们显示在视图中之前。

JSON:

[
   {
      "id":"4",
      "user_id":"4",
      "credits":"10",
      "created_at":"2013-09-30 09:39:25",
      "updated_at":"0000-00-00 00:00:00"
   },
   {
      "id":"67",
      "user_id":"4",
      "credits":"6",
      "created_at":"2013-08-05 12:40:25",
      "updated_at":"0000-00-00 00:00:00"
   }
][
   {
      "id":"6",
      "user_id":"6",
      "credits":"9",
      "created_at":"2013-06-25 16:24:18",
      "updated_at":"0000-00-00 00:00:00"
   },
   {
      "id":"69",
      "user_id":"6",
      "credits":"2",
      "created_at":"2014-01-16 10:09:55",
      "updated_at":"0000-00-00 00:00:00"
   }
]]

所以,对于那个 JSON 结果,它应该是这样的:

  1. user_id:4,总积分:16
  2. user_id:6,总积分:11

据我所知,在控制器中格式化 JSON 是有益的,而不是视图。我试过->sum()->groupBy()等功能,都没有成功。

谢谢。

更新

public function getAdminAccount()
{
    $company = User::find(Auth::user()->id)
                ->companies()
                ->with('users.credits')
                ->get()
                ->sum('credits');
    $this->layout->content = View::make('agents.admin.account', array('company' => $company));
}

上面的函数把学分总数加起来,和我需要的很接近!我只需要构成总数的每个用户的积分数!

更新

使用这个 forloop 似乎返回了正确的 MYSQL 逻辑,但仍然不是正确的值:

@foreach ($company->users as $user)
{{ $user->credits()->count('credits') }}<br>
@endforeach

MYSQL:

select count(`credits`) as aggregate from `usages` where `usages`.`user_id` = '4'

【问题讨论】:

  • 不是一个答案,但是为什么你运行一个查询来只获取 id,然后再运行一个查询来获取整个公司的 id?在companies() 之后继续with 应该就足够了。
  • 因为请求对应的是用户所在的公司。所以第一行算出用户被分配到哪个公司,然后我有公司的ID来获取用户的积分。
  • $company = User::find(Auth::user()-&gt;id)-&gt;companies()-&gt;with('users.credits')-&gt;first(); ?
  • 谢谢你,让我的查询更有效率,但是,我仍然无法统计每个用户的积分!

标签: php json laravel laravel-4


【解决方案1】:

你需要的是sum而不是count,但无论如何在循环中使用它意味着n+1问题,所以你最好这样做:

// User model
public function creditsSum()
{
    return $this->hasOne('Credit')
        ->selectRaw('user_id, sum(credits) as sum') // user_id must be in select to match the models
        ->addSelect(DB::raw('count(*) as count')) // that just in case you also need 
                                                  // credits count, if not remove
        ->groupBy('category_id');
}

// Then you can access it as easily as every relation:
User::with('creditsSum')->get();

// you will have eager loaded data on each user model:

$user->credits_sum->sum;
$user->credits_sum->count; // if you select it too

【讨论】:

  • 您好 Deczo,感谢您的回复。如果您看到我当前的功能,我只需要找到与经过身份验证的用户公司相关的那些的 user_ids。因此,第一行,获取属于该用户的公司 ID,然后是具有该对应 ID 的所有其他用户。我刚刚检查了 MYSQL,它正在搜索所有用户。
  • 是的,确实如此,这只是一个明智的例子。但是对于任何查询生成器(Auth::user()-&gt;companies()-&gt;with('users.creditsSum')-&gt;first();),它的工作原理都是一样的。用户有很多公司吗?
  • @Svengali 是的,在公司上使用first 很奇怪,因为这听起来每个用户只有一家公司。那么也许定义了错误的关系?
  • 一个用户可以属于多个公司,一个公司有多个用户。它由数据透视表标识。知道了 Deczo,它现在只提取属于该公司的人的 ID。 {{$company-&gt;credits_sum-&gt;sum}} 但是返回无对象的属性?
  • 你是绝对正确的,Laravel 也是正确的;)改变与 hasOne 的关系,就像我的编辑一样,因为 hasMany 当然会返回 Collection。我的错
【解决方案2】:

如果我以正确的方式预测您的数据库布局,我认为联接是最快的解决方案。这样您就不需要为每个用户触发查询。它也是SUM 而不是COUNT,count 只会计算数据集的数量。

$company->users()->join('credits', 'users.id', '=', 'credits.user_id')
                 ->selectRaw('SUM(credits.credits) as `total_credits`, users.username')
                 ->groupBy('credits.user_id')->get();

这应该会给你类似的东西

total_credits | username
------------------------
           24 | John
           12 | Michael

如果您还想获得没有任何信用的用户,您应该使用leftJoin

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    相关资源
    最近更新 更多