ChatGPT解决这个技术问题 Extra ChatGPT

在 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() 的特定列。我怎样才能做到这一点?


M
ManojKiran Appathurai

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

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

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

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


这很奇怪,我无法让它工作。我在 $query->select('id','username'); 中添加后,我得到了 Trying to get property of non-object
诡异的!仍然返回用户的所有字段。 @AwaisQarni
感谢您分享这一点。你是从哪里发现这种可能性的?我在 Laravel 文档中没有找到这个。
对于看到这一点的人,请记住主键(在本例中为 id)在 $query->select() 中是实际检索必要结果所必需的。我在我的代码中省略了这一点,无法弄清楚为什么它找不到任何结果。傻我!希望这可以帮助其他有同样问题的人
很好,只需要添加外键,这里它的 post_id 否则结果将为空。在这里提到外键很重要。谢谢 :)
A
Adam

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

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

注意 docs 中所述的 id 字段和 foreign keys

使用此功能时,您应该始终在要检索的列列表中包含 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']);
@Imran_Developer 用户表上的主键是什么?也许 Post::with('user:id,username')->get(['age', 'color', 'id']); 有效?
S
Supun Praneeth

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

在您的 Post 模型中

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

原始功劳归 Laravel Eager Loading - Load only specific columns


但是这种关系会使它就像硬编码一样。在所有情况下,它总是会返回我这两个字段。在某些其他情况下,我可能需要更多字段
然后您必须使用查询生成器。
这应该是公认的答案。这是正确的做法。
在 Laravel 5.3 版本中有没有办法做到这一点?我认为他们改变了它......再次......现在当我尝试使用这种方法时它返回 null
已经有一段时间了,但您可以添加一个 $fields 参数。
D
Douwe de Haan

当走另一条路时(hasMany):

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

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


是的,确切地说,“不要忘记包含外键(假设它是本示例中的 user_id)”
您应该在选择字段中包含定义您的关系的列,在这种情况下为 user_id
抓得好兄弟。
很棒的兄弟,外键的使用非常重要,幸运的是我看到了你的答案,否则我会挠头好几个小时哈哈。谢啦!
S
Shreyansh Panchal

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

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

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


不要忘记添加外键字段
不要忘记注意@hendra1 的评论,所有外键字段也必须与主键一起使用,否则您将获得空白集合。哥们节省了我的时间。谢谢
H
Haritsinh Gohil

如果您想在 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。
@Kamlesh Post::with('user:user.id,username')->get(); 此代码将返回后模型或表的所有字段,并且仅返回 users 表中的 idusername 字段,但请记住,在使用 with() 函数之前,您应该与相关表有关系您的模型,如果您没有关系,那么您可以使用查询构建器中的 join
j
jwarshaw

我遇到了这个问题,但有第二层相关对象。 @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();

哇,太棒了@jwarshaw,这就是我真正想要的,这个“user_id”真的很适合我。
C
Chris Harrison

在您的 Post 模型中:

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

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


真的吗?对我来说,这只是什么都没有返回,即它破坏了它?
你值得一个拥抱!
@Sjwdavies 您还需要在选择中添加外键
M
Maik Lowrey

还有另一种选择,您可以急切加载特定的列

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([ '姓名']);
@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 很好。
E
Elvis Reis

我想得到相同的答案而不返回 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"
      }
}

B
Bilal Ahmed

请注意,如果您只需要表格中的一列,那么使用“列表”非常好。就我而言,我正在检索用户最喜欢的文章,但我只想要文章 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 方法之间的区别很重要。
K
Kornel

如果您使用 PHP 7.4 或更高版本,您也可以使用箭头函数,这样看起来更干净:

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

S
Shreyansh Panchal

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

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


M
Mobarak Hossen

你可以试试这段代码。它在 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');
}

L
Lonare

在我的用户模型(Laravel 8.xx)中使用 belongsToMany 关系时,我遇到了同样的问题。

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

您必须确保从该关系的任一方选择该关系所需的 ID 和任何外键。这使得 Eloquent 可以将父母与他们的孩子进行匹配。

原始功劳归 https://stackoverflow.com/a/64233242/1551102

所以我包括

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

它就像一个魅力。虽然现在我想知道如何在获取后隐藏 groupid 字段。我知道我可以简单地遍历数组并将其删除。但是还有其他方法吗?可能是更简单和更好的。


哦,谢谢兄弟:),你真的节省了我的时间
G
Giovanni Far

现在您可以在 Collection 实例上使用 pluck 方法:

这将仅返回 Post modeluuid 属性

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

D
Douwe de Haan

有条件试试。

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

T
TomoMiha

因此,与我的其他解决方案类似:

// 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');

c
caiohamamura

请注意,如果您不添加 key 列,它将不会返回任何内容。如果您只想显示没有 idusername,您可以改为在模型中定义 $visible/$hidden 属性,如下所示:

应用程序/模型/User.php

protected $visible = ['username'];

然后它将仅检索 username 列:

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

隐藏关键列:

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

应用程序/模型/User.php

protected $hidden = ['id'];

指定要包含 key 的列,否则它不会返回任何内容,但这实际上只会返回用户名,因为 id$hidden

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

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

这与 this answer 中的语法相同(只是模型和列的名称不同)