【问题标题】:Laravel using select in Eloquent scope and queryLaravel 在 Eloquent 范围和查询中使用 select
【发布时间】:2015-06-13 04:07:53
【问题描述】:

我正在尝试清理我编写的一些代码。

这是当前代码:

$message = Message::with('comments')
   ->join('users', 'messages.created_by', '=', 'users.id')
   ->join('team_user', 'messages.created_by', '=', 'team_user.user_id')
   ->join('teams', 'team_user.team_id', '=', 'teams.id')
   ->join('roles', 'team_user.role_id', '=', 'roles.id')
   ->select('messages.id',  'messages.message', DB::raw('CONCAT(users.first_name, " ", users.last_name) AS created_by_name'), DB::raw('CONCAT(roles.name, " ", teams.name) AS function'))
   ->findOrFail($id); 

我试着把它变成这样:

$message = Message::with('comments')
   ->join('users', 'messages.created_by', '=', 'users.id')
   ->withFunction()
   ->findOrFail($id);

所以我创建了一个名为 withFunction 的作用域,如下所示:

return $query->join('team_user', 'messages.created_by', '=', 'team_user.user_id')
   ->join('teams', 'team_user.team_id', '=', 'teams.id')
   ->join('roles', 'team_user.role_id', '=', 'roles.id')->select(DB::raw('CONCAT(roles.name, " ", teams.name) AS function'));

但是因为我在选择特定列的地方使用了这个范围,所以我也不能在我的查询中使用 select。我希望它看起来像这样:

$message = Message::with('comments')
   ->join('users', 'messages.created_by', '=', 'users.id')
   ->withFunction()
   ->select('messages.id', 'messages.message')
   ->findOrFail($id);

所以我指定了从范围和查询本身返回的列。我知道我在一个查询中不能有 2 个选择,但是有什么办法可以做到吗?

如果您可以只返回范围内的列以在整个应用程序中使用它,那就太好了。

【问题讨论】:

  • 在单独的方法中移动一半的查询有什么意义?您可以将 how 请求放在单独的 Message 方法中,并在需要时调用它。但这只有在它在其他多个地方请求时才保持原样..
  • 尝试使用addSelect() 并告诉我是否可行。 ->withFunction()->addSelect('messages.id', 'messages.message')
  • 您可以使用 Eloquent Relation 清理复杂的连接
  • @NyanLynnHtut 好主意!尽管有一个缺点,但关系会增加数据库查询的数量。 (尽管在许多情况下这并不重要)
  • @NyanLynnHtut 我将如何将其创建为雄辩的关系。因为我只是在正常结果中添加了一个用户额外的功能。我也不想在每个 Message 模型中都查询该函数。

标签: php laravel eloquent laravel-5


【解决方案1】:

问题似乎归结为get() 的工作原理。

    $original = $this->columns;

    if (is_null($original)) {
        $this->columns = $columns;
    }

如果没有定义其他选择,Get 只会添加“*”来选择。

您要么需要在构建器上显式调用select('*')

$message = Message::with('comments')
   ->select('*')
   ->join('users', 'messages.created_by', '=', 'users.id')
   ->withFunction()
   ->select('messages.id', 'messages.message')
   ->findOrFail($id);

或将其添加到您的范围内,这是来自 5.3 项目的示例。

public function apply(Builder $builder, Model $model)
{
    if(is_null($builder->getQuery()->columns)){
        $builder->addSelect('*');
    }
    $builder->addSelect(DB::raw('...'));
}

【讨论】:

    【解决方案2】:

    看看addSelect()。当您使用 select() 时,您将覆盖所有其他选定的列,并且只选择一个。通过使用 addSelect(),您会将列附加到选定的列而不是替换它。

    因此,作为一般规则,您应该在调用任何添加列的范围之前调用 select(),并且这些范围应该使用 addSelect()。

    另外...您实际上不需要在您的范围内返回 $query,因为您正在与查询构建器对象进行交互。它有点像老式的参考文献 (&)。

    【讨论】:

    • addSelect() 像你描述的那样对我不起作用。它替换选定的列而不是附加到它们。换句话说,它和 select() 一样。
    猜你喜欢
    • 1970-01-01
    • 2019-05-08
    • 2016-08-17
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多