在Laravel Eloquent中使用“ With()”函数获取特定列


196

我有两个表,UserPost。一个User可以有许多posts,一个post只能属于一个user

在我的User模型中,我有一个hasMany关系...

public function post(){
    return $this->hasmany('post');
}

在我的post模型中,我有一个belongsTo关系...

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

现在,我想使用来连接这两个表,Eloquent with()但是想要第二个表中的特定列。我知道我可以使用查询生成器,但我不想这样做。

Post我在模型中写...

public function getAllPosts() {
    return Post::with('user')->get();
}

它运行以下查询...

select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)

但是我想要的是...

select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)

当我使用...

Post::with('user')->get(array('columns'....));

它仅返回第一个表中的列。我想使用with()第二个表中的特定列。我怎样才能做到这一点?

Answers:


345

好吧,我找到了解决方案。可以通过将closure函数with()作为数组的第二个索引传递来完成

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

它只会选择idusername从其他表中选择。我希望这会帮助其他人。


请记住,主键(在这种情况下为id)必须是 $ query-> select()中的第一个参数,才能实际检索必要的结果。*


1
奇怪,我无法解决这个问题。一旦添加进去$query->select('id','username');,我就得到了Trying to get property of non-object
user1669496 2013年

5
奇怪的!仍返回用户的所有字段。@AwaisQarni
贾斯汀

2
感谢您分享这一点。您在哪里发现这种可能性?我在Laravel文档中没有找到这个。
Symen Timmermans

79
对于那些看到此内容的人,请记住,主键(id在这种情况下)是$query->select()实际检索必要结果所必需的。我在代码中忽略了这一点,无法弄清为什么找不到任何结果。傻我!希望这对其他有相同问题的人
有所

4
太好了,只需要添加外键,在这里添加其post_id,否则结果将为空。这里提到外键很重要。谢谢:)
哈沙姆·艾哈迈德

102

从Laravel 5.5开始,您可以这样做:

Post::with('user:id,username')->get();

照管该id领域,并foreign keys按照文档所述

使用此功能时,应始终在要检索的列列表中包括id列和所有相关的外键列。

例如,如果用户属于团队并且有一个team_id作为外键列,那么$post->user->team如果您未指定则为空 team_id

Post::with('user:id,username,team_id')->get();

13
不要忘记包含外键(假设此处为post_id)来解决该关系,否则您的关系将得到空结果。
哈沙姆·艾哈迈德

2
这确实应该是选择的答案。像魅力一样工作:)
Graham

@Adam,这将限制子表中的列,如何限制父表和子表中的列?

要从parant belogns在限制@GauravGenius一切get()方法Post::with('user:id,username')->get(['age', 'color']);
亚当

82

在您的Post模型中

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

原始功劳归Laravel渴望加载-仅加载特定列


14
但是这种关系会使它像硬编码一样。在所有情况下,它将始终返回这两个字段。在其他情况下,我可能需要更多字段
Awais Qarni

然后,您必须使用查询生成器。
user1669496 2013年

5
这应该是公认的答案。这是正确的方法。
BugHunterUK

1
Laravel 5.3版本中有没有办法做到这一点?我认为他们再次更改了它....现在,当我尝试这种方法时,它返回null
Andre F.

已经有一段时间了,但是您可以添加一个$fields参数。
JordyvD

69

当以另一种方式走(hasMany)时:

User::with(array('post'=>function($query){
    $query->select('id','user_id');
}))->get();

不要忘记包含外键(假设在此示例中为user_id)来解决该关系,否则您的关系将得到零结果。


6
是的,确切地说,“不要忘记包含外键(假设在此示例中为外键)”
aqingsao

您应该在选择字段中包括定义您的关系的列,在这种情况下,user_id
alimfazeli

不错的兄弟。
Shahrukh Anwar

棒极了,使用外键非常重要,很幸运,我看到了您的回答,否则我会挠头几个小时大声笑。谢啦!
哈沙姆·艾哈迈德

34

在Laravel 5.7中,您可以像这样调用特定字段

$users = App\Book::with('author:id,name')->get();

foreign_key在选择中添加字段很重要。


11
别忘了添加外键字段
hendra1 '18

2
不要忘了注意@ hendra1的注释,所有外键字段和主键也都是必需的,否则您将获得空白集合。杜德节省了我的时间。感谢
Rajesh Vishnani '18

14

在您的Post模型中:

public function userWithName()
{
    return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}

现在您可以使用 $post->userWithName


2
真?对我来说,这什么也不会返回,即会破坏它吗?
Sjwdavies

12

如果你想使用得到特定的列with()在laravel口若悬河,那么你可以使用代码如下它最初是由@Adam在他的回答回答这里在这同一个问题的回答:

Post::with('user:id,username')->get();

所以我在代码中使用了它,但是给了我错误1052: Column 'id' in field list is ambiguous所以如果你们也遇到同样的问题

为了解决这个问题,您必须在with()方法的id列之前指定表名,如下代码

Post::with('user:user.id,username')->get();

这对我来说返回null,但我之前不知道这是可能的!好的,所以我发布了prematurley,但确实找到了结果。要使用此方法(看上去更简洁),您必须包括关系链接,例如,在提取with数据时使用ID列。没有此说明符,您将获得空返回。
adsy2010

是的@ Adsy2010,要获取相关的关系数据,您还必须获取ID列或主键,或负责该关系的ID。
Haritsinh Gohil

10

我遇到了这个问题,但遇到了第二层相关对象。@Awais Qarni的答案在嵌套的select语句中包含了适当的外键。就像在第一个嵌套的select语句中需要一个id来引用相关模型一样,需要外键来引用第二级相关模型;在此示例中,公司模型。

Post::with(['user' => function ($query) {
        $query->select('id','company_id', 'username');
    }, 'user.company' => function ($query) {
        $query->select('id', 'name');
    }])->get();

此外,如果要从Post模型中选择特定的列,则需要在select语句中包括user_id列以进行引用。

Post::with(['user' => function ($query) {
        $query->select('id', 'username');
    }])
    ->select('title', 'content', 'user_id')
    ->get();

4

请注意,如果您只需要表中的一列,那么使用“列表”是相当不错的。就我而言,我正在检索用户最喜欢的文章,但我只想要文章ID:

$favourites = $user->favourites->lists('id');

返回一个ID数组,例如:

Array
(
    [0] => 3
    [1] => 7
    [2] => 8
)

它返回一个集合!
乔瓦尼(Giovanni)2015年

如果您想要一个数组,请致电toArray()$user->favourites->lists('id')->toArray();
乔瓦尼(Giovanni)2015年

该查询仍将获取其他列,因为list()方法只是更改了结果数组,因此,如果您只需要该表中的“ id”,则可能需要在查询中指定它。在执行查询时始终牢记性能始终是一个好习惯。享受编码!
Ervin Llojku '16

$user->favourites将返回-1,并Collection选择所有字段。正确的用法是:$user->favourites()->lists('id')
华莱士·麦克斯特斯

选择所有内容以供以后使用PHP过滤是一个坏主意。最好仅在查询中使用所需的字段。了解Query\Builder::lists方法与Collection::lists方法之间的区别很重要。
华莱士·麦克斯特斯


0

现在,您可以pluckCollection实例上使用该方法:

这将只返回uuid的属性Post model

App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
     all: [
       "1",
       "2",
       "3",
     ],
   }


-3
EmployeeGatePassStatus::with('user:id,name')->get();

1
这是与该答案相同的语法(只是模型和列的名称不同)
barbsan
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.