I have two tables, User
and Post
. One User
can have many posts
and one post
belongs to only one user
.
In my User
model I have a hasMany
relation...
public function post(){
return $this->hasmany('post');
}
And in my post
model I have a belongsTo
relation...
public function user(){
return $this->belongsTo('user');
}
Now I want to join these two tables using Eloquent with()
but want specific columns from the second table. I know I can use the Query Builder but I don't want to.
When in the Post
model I write...
public function getAllPosts() {
return Post::with('user')->get();
}
It runs the following queries...
select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)
But what I want is...
select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)
When I use...
Post::with('user')->get(array('columns'....));
It only returns the column from the first table. I want specific columns using with()
from the second table. How can I do that?
Well I found the solution. It can be done one by passing a closure
function in with()
as second index of array like
Post::query()
->with(array('user' => function($query) {
$query->select('id','username');
}))
->get();
It will only select id
and username
from other table. I hope this will help others.
Remember that the primary key (id in this case) needs to be the first param in the $query->select()
to actually retrieve the necessary results.*
You can do it like this since Laravel 5.5:
Post::with('user:id,username')->get();
Care for the id
field and foreign keys
as stated in the docs :
When using this feature, you should always include the id column and any relevant foreign key columns in the list of columns you wish to retrieve.
For example, if the user belongs to a team and has a team_id
as a foreign key column, then $post->user->team
is empty if you don't specifiy team_id
Post::with('user:id,username,team_id')->get();
Also, if the user belongs to the post (ie there is a column post_id
in the users
table), then you need to specify it like this:
Post::with('user:id,username,post_id')->get();
Otherwise $post->user
will be empty.
For loading models with specific column, though not eager loading, you could:
In your Post
model
public function user()
{
return $this->belongsTo('User')->select(['id', 'username']);
}
Original credit goes to Laravel Eager Loading - Load only specific columns
When going the other way (hasMany):
User::with(array('post'=>function($query){
$query->select('id','user_id');
}))->get();
Don't forget to include the foreign key (assuming it is user_id in this example) to resolve the relationship, otherwise you'll get zero results for your relation.
In Laravel 5.7 you can call specific field like this
$users = App\Book::with('author:id,name')->get();
It is important to add foreign_key
field in the selection.
If you want to get specific columns using with()
in laravel eloquent then you can use code as below which is originally answered by @Adam in his answer here in response of this same question, the answer's main code is as below :
Post::with('user:id,username')->get();
So i have used it in my code but it was giving me error of 1052: Column 'id' in field list is ambiguous
, so if you guys are also facing same problem
Then for solving it you have to specify table name before the id column in with()
method as below code :
Post::with('user:user.id,username')->get();
I came across this issue but with a second layer of related objects. @Awais Qarni's answer holds up with the inclusion of the appropriate foreign key in the nested select statement. Just as an id is required in the first nested select statement to reference the related model, the foreign key is required to reference the second degree of related models; in this example the Company model.
Post::with(['user' => function ($query) {
$query->select('id','company_id', 'username');
}, 'user.company' => function ($query) {
$query->select('id', 'name');
}])->get();
Additionally, if you want to select specific columns from the Post model you would need to include the user_id column in the select statement in order to reference it.
Post::with(['user' => function ($query) {
$query->select('id', 'username');
}])
->select('title', 'content', 'user_id')
->get();
In your Post
model:
public function userWithName()
{
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}
Now you can use $post->userWithName
Note that if you only need one column from the table then using 'lists' is quite nice. In my case i am retrieving a user's favourite articles but i only want the article id's:
$favourites = $user->favourites->lists('id');
Returns an array of ids, eg:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
如果你使用 PHP 7.4 或更高版本,你也可以使用箭头函数来做,这样看起来更干净:
Post::with(['user' => fn ($query) => $query->select('id','username')])->get();
There is another alternative you can eager load specific columns
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);
}
In your Post
model you should have user
relationship also
public function user()
{
return $this->belongsTo( User::class, 'user_id')->withDefault();
}
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-specific-columns
您还可以在访问时指定相关模型上的列。
Post::first()->user()->get(['columns....']);
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); }
Model code
public function sectionType(){ return $this->belongsTo(Section_Type::class, 'type_id'); }
Now you can use the pluck
method on a Collection
instance:
This will return only the uuid
attribute of the Post model
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
all: [
"1",
"2",
"3",
],
}
Try with conditions.
$id = 1;
Post::with(array('user'=>function($query) use ($id){
$query->where('id','=',$id);
$query->select('id','username');
}))->get();
As you set relation in model try this
$postdata = Post::with('user')->get();
$posdata = $postdata->map(function(posts){
return collection([
............
...........
'user' => $posts->user->map(function($user){
'id' => $user->id,
'username' => $user->username
})
])
})
So, similar to other solutions here is mine:
// 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');
I faced the same issue while using belongsToMany relationship with my user model (Laravel 8.xx).
After a long search and trial and test method. I found out this answer
You have to make sure you are selecting the id's and any foreign keys that would be needed for the relationship from either side of that relationship. This allows Eloquent to match up parents to their children.
Original credit goes to https://stackoverflow.com/a/64233242/1551102
So I included
Groups::select('groupid')
...
And it worked like a charm. Although now I want to know how to hide the groupid field after fetching. I know I can simply loop through the array and remove it. But is there any other method? potentially a simpler and better one.
Be careful that if you don't add the key
column(s) it won't return anything. If you want to show only the username
without the id
you could instead define the $visible/$hidden
properties within the Model, like so:
protected $visible = ['username'];
Then it will retrieve only username
column with:
Post::with('user')->get();
key
columns: Alternatively you could hide the key
column(s) and then retrieve only the columns you wish.
protected $hidden = ['id'];
Specify which columns you want including the key
or else it won't return anything, but this will actually only return the username, because id
is $hidden
.
Post::with('user:id,username')->get();
I would like to have the same answer without returning the estado_id
$this->cidade
->with('estado:id,nome')
->select(['id', 'nome', 'estado_id']);
when I don't enter the estado_id in the select
{
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado": null
}
when I enter the estado_id in the select
{
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado_id": 11,
"estado": {
"id": 11,
"nome": "Rondônia"
}
}
expected
{
"id": 1100015,
"nome": "Alta Floresta D'Oeste",
"estado": {
"id": 11,
"nome": "Rondônia"
}
}
EmployeeGatePassStatus::with('user:id,name')->get();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.