Laravel Eloquent:如何仅从联接表中获取某些列


102

我在Eloquent中有2个联接表,即主题和用户。

主题模型:

public function user() {
  return $this->belongs_to('User');
}

用户模型:

public function themes() {
  return $this->has_many('Theme');
}

我的口才api调用如下所示:

return Response::eloquent(Theme::with('user')->get());

它返回主题的所有列(很好),以及用户的所有列(不好)。我只需要用户模型中的“用户名”列,如何将查询限制于此?


我正在执行类似的任务,Response请问我是否使用需要导入的类?
Agnes Palit

Answers:


103

更改模型以指定要选择的列:

public function user() {
  return $this->belongs_to('User')->select(array('id', 'username'));
}

并且不要忘记添加您要加入的列。


6
很好的答案,关于加入连接列的提示也节省了我很多时间!
greatwitenorth

如果在某些地方我只需要ID而不是ID和用户名怎么办?还是必须同时选择两者?
Darius.V,2015年

嗨,select函数在模型查询生成器中具有相同的功能吗?
Gokigooooks 2015年

4
我认为这不是一个好方法。这将对列名进行硬编码。所有地点将仅返回这些列。在其他一些api中,我可能需要更多列,因此在这里不起作用。我认为使用QueryBuilder是这里的选择。
阿曼苏拉(Aman Sura)

2
这是一种引人注目的方法,因为每次拨打电话时都会发生这种情况。我相信Sajjad Ashraf的回答是大多数人会感兴趣的答案
。– MMMTroy

37

对于Laravel> = 5.2

使用-> pluck()方法

$roles = DB::table('roles')->pluck('title');

如果要检索包含单个列的值的数组,则可以使用pluck方法


对于Laravel <= 5.1

使用-> lists()方法

$roles = DB::table('roles')->lists('title');

此方法将返回角色标题数组。您还可以为返回的数组指定一个自定义键列:


2
这实际上不是问题的答案(特别是关于联接/关系)。
orrd

30

您可以在get参数中提供一个字段数组,如下所示:

return Response::eloquent(Theme::with('user')->get(array('user.username'));

UPDATE(对于Laravel 5.2)在docs中,您可以执行以下操作:

$response = DB::table('themes')
    ->select('themes.*', 'users.username')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get();

2
我尝试了这个,它显示了一个错误SQLSTATE[42S22]: Column not found,并且SQL不包含中的表with。错误上显示的sql是“ SELECT fk_table.column1 FROM main_table”。
米歇尔·艾尔斯2015年

1
它是“ users.username”(不是“ user.username”)。如果表名和列名与实际数据库匹配,则答案中的代码将起作用。这是该解决方案的缺点,它是在构建SQL查询而不是使用Eloquent,因此名称必须与实际的数据库表和列匹配。
orrd

22

我知道,您要求口才好,但您可以使用Fluent Query Builder来做到这一点

$data = DB::table('themes')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get(array('themes.*', 'users.username'));

16

这就是我的方法

$posts = Post::with(['category' => function($query){
        $query->select('id', 'name');
      }])->get();

user2317976的第一个答案对我不起作用,我使用的是laravel 5.1


2
最新答案=有用!
thesunneversets

谢谢。这对我来说可以。我必须像选择“ id”一样,将外键添加到select语句中,否则它将返回null。
Iman Sedighi

但是,这仍然为每个结果检索一个“枢轴”字段,其中包含两个ID(post_id和category_id),对吗?我怎样才能乘坐呢?
mayid

1
@mayid,您可以尝试将其添加pivot到$ hidden的Post Model数组中protected $hidden = ['pivot']
Sajjad Ashraf,

这是最好的解决方案(假设您使用的是Laravel的相当现代的版本)
2014年

11

另一种选择是利用$hidden模型上的属性来隐藏您不想显示的列。您可以动态定义此属性,也可以在模型上设置默认值。

public static $hidden = array('password');

现在,当您返回JSON响应时,用户密码将被隐藏。

您也可以以类似方式即时设置它。

User::$hidden = array('password');

2
在Laravel 4.2中,尝试动态设置此属性时,出现“无法访问受保护的属性User :: $ hidden”。
mtmacdonald 2014年

1
不应该这样static
StackOverflowed 2015年

@StackOverflowed,我想你没有采取这个问题/答案是几岁的通知,这关系到Laravel 3
贾森·刘易斯

10

分页使用

$data = DB::table('themes')
->join('users', 'users.id', '=', 'themes.user_id')
->select('themes.*', 'users.username')
->paginate(6);

6

user2317976引入了一种很棒的静态方式来选择相关表的列。

这是我发现的动态技巧,因此您可以在使用模型时获得所需的一切:

return Response::eloquent(Theme::with(array('user' => function ($q) {
    $q->addSelect(array('id','username'))
}))->get();

我刚刚发现这个技巧也可以与load()一起使用。这很方便。

$queriedTheme->load(array('user'=>function($q){$q->addSelect(..)});

确保还包括目标表的键,否则将无法找到它。


6

这条路:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();

请始终解释您的答案。
罗希特·古普塔

遇到类似的问题,这是迄今为止最明智的方法!这个答案被低估了!
eldblz

这与Sajjad Ashraf先前已经提交的答案相同。
orrd

5

我知道这是一个古老的问题,但是,如果您要像问题的作者一样构建API,请使用输出转换器执行此类任务。

Transofrmer是您实际的数据库查询结果和控制器之间的一层。它允许轻松地控制和修改将要输出给用户或API使用者的内容。

我建议Fractal作为您的输出转换层的坚实基础。您可以在此处阅读文档。



4

在Laravel 5.5上,最干净的方法是:

Theme::with('user:userid,name,address')->get()

您添加一个冒号,并且希望选择的字段之间用逗号隔开,并且它们之间没有空格。


您知道使用分页时如何获取相关表的特定列。
Daniyal Nasir

2

使用模型:

Model::where('column','value')->get(['column1','column2','column3',...]);

使用查询生成器:

DB::table('table_name')->where('column','value')->get(['column1','column2','column3',...]);

0

如果我能很好地理解这一点,那么返回的内容就很好,但您只希望看到一列。如果是这样,则下面的代码应该简单得多:

return Response::eloquent(Theme::with('user')->get(['username']));

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.