在 Laravel Eloquent 中使用“With()”函数获取特定列
Posted
技术标签:
【中文标题】在 Laravel Eloquent 中使用“With()”函数获取特定列【英文标题】:Get Specific Columns Using “With()” Function in Laravel Eloquent 【发布时间】:2013-11-20 02:25:36 【问题描述】:我有两张桌子,User
和 Post
。一个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()
的特定列。我该怎么做?
【问题讨论】:
【参考方案1】:好吧,我找到了解决方案。它可以通过在with()
中传递一个closure
函数作为数组的第二个索引来完成,例如
Post::query()
->with(['user' => function ($query)
$query->select('id', 'username');
])
->get()
它只会从其他表中选择id
和username
。我希望这对其他人有帮助。
请记住,主键(在本例中为 id)需要是第一个参数
$query->select()
实际检索必要的结果。*
【讨论】:
这很奇怪,我无法让它工作。一旦我添加了$query->select('id','username');
,我就得到了Trying to get property of non-object
奇怪!仍然返回用户的所有字段。 @AwaisQarni
感谢您分享此内容。你是从哪里发现这种可能性的?我在 Laravel 文档中没有找到这个。
对于那些看到这个的人,请记住主键(在这种情况下为id
)在$query->select()
中是必需的,以实际检索必要的结果。我在我的代码中省略了这一点,无法弄清楚为什么它找不到任何结果。傻我!希望这可以帮助其他有同样问题的人
很好,只需要添加外键,这里的post_id 否则结果为空。在这里提到外键很重要。谢谢:)【参考方案2】:
我希望得到相同的答案而不返回 estado_id
$this->cidade
->with('estado:id,nome')
->select(['id', 'nome', 'estado_id']);
当我没有在选择中输入 estado_id 时
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado": null
当我在选择中输入 estado_id 时
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado_id": 11,
"estado":
"id": 11,
"nome": "Rondônia"
预计
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado":
"id": 11,
"nome": "Rondônia"
【讨论】:
【参考方案3】:还有另一种选择,您可以预先加载特定的列
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
【讨论】:
你能帮忙吗,它返回产品名称但不返回“用户”对象:$product = Product::where('id', $p_id)->with('user:id, name')->get(['name']); @Imran_Developer 因为您只在 get(['name']) 中返回名称。这样做 $product = Product::with('user:id,name')->where('id', $p_id)->get(); 是的,亲爱的@Neeraj,但它返回给我的用户对象是所有产品列而不是 1 或 2。但我已经通过使用:$product = Product::with('user:id,name')->where('id', $p_id)->select('title', 'content', 'user_id')->get();
解决了这个问题。这里的“user_id”是很重要的参考。
@Imran_Developer 很好。【参考方案4】:
请注意,如果您不添加 key
列,它将不会返回任何内容。如果您只想显示 username
而不显示 id
您可以改为在模型中定义 $visible/$hidden
属性,如下所示:
app/Models/User.php
protected $visible = ['username'];
然后它将只检索username
列:
Post::with('user')->get();
隐藏key
列:
或者,您可以隐藏 key
列,然后只检索您想要的列。
app/Models/User.php
protected $hidden = ['id'];
指定您想要包含key
的列,否则它不会返回任何内容,但这实际上只会返回用户名,因为id
是$hidden
。
Post::with('user:id,username')->get();
【讨论】:
【参考方案5】:在我的用户模型 (Laravel 8.x.x) 中使用 belongsToMany 关系时,我遇到了同样的问题。
经过长时间的搜索和试验和测试方法。我找到了这个答案
您必须确保从关系的任一方选择关系所需的 ID 和任何外键。这允许 Eloquent 将父母与他们的孩子进行匹配。
原始信用归https://***.com/a/64233242/1551102
所以我包括
Groups::select('groupid')
...
它就像一个魅力。虽然现在我想知道如何在获取后隐藏 groupid 字段。 我知道我可以简单地遍历数组并将其删除。但是还有其他方法吗?可能更简单更好。
【讨论】:
哦,谢谢兄弟 :),你真的节省了我的时间【参考方案6】:对于加载具有特定列的模型,虽然不是预先加载,但您可以:
在您的Post
模型中
public function user()
return $this->belongsTo('User')->select(['id', 'username']);
原始信用归Laravel Eager Loading - Load only specific columns
【讨论】:
但是这种关系会让它就像硬编码一样。在所有情况下,它总是会返回我这两个字段。在某些其他情况下,我可能需要更多字段 那么你必须使用查询生成器。 这应该是公认的答案。这是正确的做法。 有没有办法在 Laravel 5.3 版本中做到这一点?我认为他们改变了它......再次......现在当我尝试使用这种方法时它返回 null 已经有一段时间了,但您可以添加一个$fields
参数。【参考方案7】:
如果您想在 laravel eloquent 中使用 with()
获取特定列,那么您可以使用下面的代码,@Adam 在他的回答 here 中最初回答了同样的问题,答案的主要代码如下下面:
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,但我确实找到了结果。要使用此方法(看起来更干净),您必须包含关系链接,例如拉取数据时的 ID 列。没有这个说明符,你会得到一个空返回。 是的@Adsy2010,要获取相关关系数据,您还必须获取 id 列或主键或负责该关系的任何 id。 @KamleshPost::with('user:user.id,username')->get();
此代码将返回后模型或表的所有字段,并且仅返回 users
表中的 id
和 username
字段,但在使用 with()
函数之前请记住您应该与模型中的相关表有关系,如果没有关系,则可以使用查询生成器中的join。【参考方案8】:
从 Laravel 5.5 开始你就可以这样做了:
Post::with('user:id,username')->get();
注意id
字段和foreign keys
,如docs 中所述:
使用此功能时,您应该始终包含 id 列和 您希望列列表中的任何相关外键列 检索。
例如,如果用户属于一个团队并且有一个team_id
作为外键列,那么如果你不指定team_id
,那么$post->user->team
是空的
Post::with('user:id,username,team_id')->get();
另外,如果用户属于帖子(即users
表中有post_id
列),那么您需要这样指定:
Post::with('user:id,username,post_id')->get();
否则$post->user
将为空。
【讨论】:
不要忘记包含外键(假设这里是 post_id)来解析关系,否则你的关系会得到空结果。 这确实应该是选择的答案。像魅力一样工作:) @Adam,这将限制子表中的列,如何限制父表和子表中的列? @GauravGenius 在get()
方法Post::with('user:id,username')->get(['age', 'color']);
中您想限制的所有内容都来自parant
@Imran_Developer 你的用户表上的主键是什么?也许Post::with('user:id,username')->get(['age', 'color', 'id']);
有效?【参考方案9】:
你可以试试这个代码。它在 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');
【讨论】:
【参考方案10】:如果你使用 PHP 7.4 或更高版本,你也可以使用箭头函数,这样看起来更干净:
Post::with(['user' => fn ($query) => $query->select('id','username')])->get();
【讨论】:
【参考方案11】:所以,与我的其他解决方案类似:
// 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');
【讨论】:
【参考方案12】:当走另一条路时(hasMany):
User::with(array('post'=>function($query)
$query->select('id','user_id');
))->get();
不要忘记包含外键(假设在此示例中为 user_id)来解析关系,否则您的关系将得到零结果。
【讨论】:
是的,确切地说,“不要忘记包含外键(假设在本例中是 user_id)” 您应该在选择字段中包含定义您的关系的列,在本例中为 user_id 好哥们儿。 太棒了兄弟,外键的使用真的很重要,幸运的是我看到了你的答案,否则我会挠头好几个小时哈哈。谢谢大佬!【参考方案13】:根据条件尝试。
$id = 1;
Post::with(array('user'=>function($query) use ($id)
$query->where('id','=',$id);
$query->select('id','username');
))->get();
【讨论】:
【参考方案14】:EmployeeGatePassStatus::with('user:id,name')->get();
【讨论】:
这与this answer 中的语法相同(只是模型和列的名称不同)【参考方案15】:在 Laravel 5.7 中,您可以像这样调用特定字段
$users = App\Book::with('author:id,name')->get();
在选择中添加foreign_key
字段很重要。
【讨论】:
别忘了添加外键字段 别忘了注意@hendra1 的评论,所有的外键字段和主键也是必须的,否则你会得到空白集合。哥们节省了我的时间。谢谢【参考方案16】:我遇到了这个问题,但有第二层相关对象。 @Awais Qarni 的回答支持在嵌套的 select 语句中包含适当的外键。就像在第一个嵌套的select语句中需要一个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();
【讨论】:
哇,太棒了@jwarshaw,这就是我真正想要的,这个“user_id”真的很适合我。【参考方案17】:您还可以在访问相关模型时指定列。
Post::first()->user()->get(['columns....']);
【讨论】:
【参考方案18】:请注意,如果您只需要表格中的一列,那么使用“列表”非常好。就我而言,我正在检索用户最喜欢的文章,但我只想要文章 ID:
$favourites = $user->favourites->lists('id');
返回一个id数组,例如:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
【讨论】:
它返回一个集合! 如果你想要一个数组然后调用toArray()
!!! $user->favourites->lists('id')->toArray();
查询仍将获取其他列,因为 list() 方法只是更改了结果数组,因此如果您只需要该表中的“id”,您可能需要在查询中指定它。在进行查询时牢记性能始终是一个好习惯。享受编码!
-1 $user->favourites
将返回 Collection
并选择所有字段。正确用法是:$user->favourites()->lists('id')
.
选择所有内容以供以后使用 PHP 过滤是一个坏主意。最好只使用 Query 中所需的字段。了解Query\Builder::lists
方法和Collection::lists
方法之间的区别很重要。【参考方案19】:
现在您可以在Collection
实例上使用pluck
方法:
这将只返回Post model
的uuid
属性
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection #983
all: [
"1",
"2",
"3",
],
【讨论】:
【参考方案20】:在您的Post
模型中:
public function userWithName()
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
现在你可以使用$post->userWithName
【讨论】:
真的吗?对我来说,这只会返回任何内容,即它会破坏它? 你值得拥抱! @Sjwdavies 您还需要在选择中添加外键以上是关于在 Laravel Eloquent 中使用“With()”函数获取特定列的主要内容,如果未能解决你的问题,请参考以下文章
在 Eloquent 查询/Laravel 5.2 中使用变量
Laravel:在 API 测试中使用 Eloquent 模型
如何在 Laravel 5.8 中使用 Eloquent 进行查询?
在 Laravel 中使用 Eloquent 进行更高级的数据库查询