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

我有两个表,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()指定列。我该怎么做呢?

469179 次浏览

对于具有特定列的加载模型,虽然不是立即加载,但您可以:

在你的Post模型中

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

原始信用归Laravel快速加载-只加载特定的列

我找到解决办法了。可以通过在with()中传递closure函数作为数组的第二个索引来实现

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

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


中的主键(在本例中是id)需要是第一个参数 *

. $query->select()来实际检索必要的结果

注意,如果你只需要表中的一列,那么使用'lists'是非常好的。在我的情况下,我正在检索用户最喜欢的文章,但我只想要文章id的:

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

返回一个id数组,例如:

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

当走另一条路(hasMany):

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

不要忘记包含外键(假设在本例中为user_id)来解析关系,否则关系将得到零结果。

在你的Post模型中:

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

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

现在你可以在Collection实例上使用__abc0方法:

这将只返回Post modeluuid属性

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

从Laravel 5.5开始你就可以这样做了:

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

注意id字段和foreign keys,如文档中所述:

当使用这个特性时,你应该总是包含id列和 列列表中的任何相关外键列 检索。< / p >

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

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

同样,如果用户属于post(即在users表中有一个列post_id),那么你需要像这样指定它:

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

否则$post->user将为空。

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

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

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

您还可以在访问相关模型时指定该模型的列。

Post::first()->user()->get(['columns....']);

我遇到了这个问题,但涉及到第二层相关对象。@Awais Qarni的答案是在嵌套的选择语句中包含适当的外键。就像在第一个嵌套的选择语句中需要一个id来引用相关模型一样,外键也需要引用第二级相关模型;在本例中是Company模型。

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();
EmployeeGatePassStatus::with('user:id,name')->get();

有条件的尝试。

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

如果你想在laravel eloquent中使用with()获得特定的列,那么你可以使用下面的代码,这最初是由@Adam在他的回答在这里中回答这个相同的问题,答案的主要代码如下所示:

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

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

然后求解你必须在with()方法的id列之前指定表名,如下所示:

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

所以,类似于其他的解决方案是我的:

// For example you have this relation defined with "user()" method
public function user()
{
return $this->belongsTo('User');
}
// Just make another one defined with "user_frontend()" method
public function user_frontend()
{
return $this->belongsTo('User')->select(array('id', 'username'));
}


// Then use it later like this
$thing = new Thing();
$thing->with('user_frontend');


// This way, you get only id and username,
// and if you want all fields you can do this


$thing = new Thing();
$thing->with('user');

如果你使用php7.4或更高版本,你也可以使用箭头函数,这样看起来更干净:

Post::with(['user' => fn ($query) => $query->select('id','username')])->get();

您可以试试这段代码。在laravel 6版本中进行了测试。

控制器代码
 public function getSection(Request $request)
{


Section::with(['sectionType' => function($q) {
$q->select('id', 'name');
}])->where('position',1)->orderBy('serial_no', 'asc')->get(['id','name','','description']);
return response()->json($getSection);
}
模型代码
public function sectionType(){
return $this->belongsTo(Section_Type::class, 'type_id');
}

还有另一种方法可以加载特定的列

public function show(Post $post)
{
$posts = $post->has('user')->with('user:id,name,email,picture')->findOrFail($post->id);
return view('your_blade_file_path',compact('posts);
}

在你的Post模型中,你也应该有user关系

public function user()
{
return $this->belongsTo( User::class, 'user_id')->withDefault();
}

注意:Laravel文档中提到了它。

https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-specific-columns

在我的用户模型中使用belongsToMany关系时,我也遇到了同样的问题。

经过长时间的搜索和试验和测试方法。我找到了这个答案

您必须确保从关系的任何一方选择了关系所需的id和任何外键。这使得Eloquent能够匹配父母和孩子。

原始信用归https://stackoverflow.com/a/64233242/1551102

所以我包括了

Groups::select('groupid')
...

它就像一个咒语。尽管现在我想知道如何在取回后隐藏groupid字段。 我知道我可以简单地遍历数组并删除它。但是还有其他方法吗?

注意,如果你不添加key列,它将不会返回任何东西。如果你想只显示username而不显示id,你可以在模型中定义$visible/$hidden属性,如下所示:

应用程序/模型/ User.php

protected $visible = ['username'];

然后它将只检索username列,其中包括:

Post::with('user')->get();

隐藏key列:

或者,你可以隐藏key列,然后只检索你想要的列。

应用程序/模型/ User.php

protected $hidden = ['id'];

指定你想要的列,包括key,否则它不会返回任何东西,但这实际上只会返回用户名,因为id$hidden

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