Laravel在Eloquent范围和查询中使用select

时间:2015-04-08 09:17:17

标签: php laravel eloquent laravel-5

我试图清理我制作的一些代码。

这是当前的代码:

$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个,但是有什么方法可以做到这一点吗?

如果您可以只返回范围中的列以在整个应用程序中使用它,那将会很棒。

2 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:3)

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

    $original = $this->columns;

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

如果没有定义其他选择,则仅添加“*”以选择。

您需要在构建器

上显式调用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('...'));
}