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

时间:2013-11-08 06:30:34

标签: php laravel orm eloquent laravel-query-builder

我有两个表,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()的特定列。我怎么能这样做?

18 个答案:

答案 0 :(得分:273)

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

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

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


  

请记住主键(在本例中为id)需要是第一个参数   $ query-&gt; select()实际检索必要的结果。*

答案 1 :(得分:64)

Post模型中

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

原始信用转到Laravel Eager Loading - Load only specific columns

答案 2 :(得分:45)

你可以在Laravel 5.5中这样做:

closedIssuesList.Concat(datesList.Where(date => !closedIssuesList.Any(pair => pair.Week == date))
                                 .Select(date => new { Week = date, Count = 0 });

关注docs中所述的Post::with('user:id,username')->get(); 字段:

  

使用此功能时,您应始终包含id列   您要检索的列的列表。

答案 3 :(得分:26)

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

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

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

答案 4 :(得分:12)

Post模型中:

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

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

答案 5 :(得分:3)

请注意,如果您只需要表格中的一列,那么使用&#39;列表&#39;非常好。在我的情况下,我正在检索用户最喜欢的文章,但我只想要文章ID:

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

返回一个id数组,例如:

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

答案 6 :(得分:3)

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

答案 7 :(得分:2)

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

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();
    }

注意:larave 文档中提到了这一点。

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

答案 8 :(得分:1)

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

答案 9 :(得分:1)

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

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

答案 10 :(得分:1)

如果您想用laravel雄辩地使用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();

答案 11 :(得分:0)

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

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

您必须确保从该关系的任一侧选择该关系所需的 id 和任何外键。这使得 Eloquent 可以将父母与孩子相匹配。

原来的功劳归于 https://stackoverflow.com/a/64233242/1551102

所以我包括了

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

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

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

在模型中设置关系时,请尝试

$postdata = Post::with('user')->get();

$posdata = $postdata->map(function(posts){
    return collection([
        ............
        ...........

        'user' => $posts->user->map(function($user){
                'id' => $user->id,
                'username' => $user->username
                })

            ])
        })

答案 14 :(得分:0)

尝试使用条件。

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

答案 15 :(得分:0)

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

答案 16 :(得分:0)

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

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

答案 17 :(得分:0)

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

这将只返回uuid

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