J'ai deux tables, User
et Post
. Une User
peut avoir plusieurs posts
et une post
appartient à une seule user
.
Dans mon modèle User
, j'ai une relation hasMany
...
public function post(){
return $this->hasmany('post');
}
Et dans mon modèle post
, j'ai une relation belongsTo
...
public function user(){
return $this->belongsTo('user');
}
Maintenant, je veux joindre ces deux tables en utilisant Eloquent with()
mais je veux des colonnes spécifiques de la seconde table. Je sais que je peux utiliser le Générateur de requêtes, mais je ne le souhaite pas.
Quand j'écris dans le modèle Post
.
public function getAllPosts() {
return Post::with('user')->get();
}
Il lance les requêtes suivantes ...
select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)
Mais ce que je veux c'est ...
select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)
Quand j'utilise ...
Post::with('user')->get(array('columns'....));
Il ne retourne que la colonne de la première table. Je veux des colonnes spécifiques en utilisant with()
de la deuxième table. Comment puis je faire ça?
Eh bien j'ai trouvé la solution. Cela peut être fait en passant une fonction closure
dans with()
en tant que deuxième index du tableau comme
Post::with(array('user'=>function($query){
$query->select('id','username');
}))->get();
Il ne sélectionnera que id
et username
dans une autre table. J'espère que cela aidera les autres.
Rappelez-vous que la clé primaire (id dans ce cas) est nécessaire dans le fichier $ query-> select () pour récupérer les résultats nécessaires. *
Dans votre modèle Post
public function user()
{
return $this->belongsTo('User')->select(array('id', 'username'));
}
Le crédit initial va à Laravel Eager Loading - Ne chargez que des colonnes spécifiques
En allant dans l'autre sens (hasMany):
User::with(array('post'=>function($query){
$query->select('id','user_id');
}))->get();
N'oubliez pas d'inclure la clé étrangère (en supposant qu'il s'agisse de user_id dans cet exemple) pour résoudre la relation, sinon vous n'obtenez aucun résultat.
Vous pouvez le faire comme ceci dans Laravel 5.5:
Post::with('user:id,username')->get();
Prenez soin du champ id
comme indiqué dans la docs :
Lorsque vous utilisez cette fonctionnalité, vous devez toujours inclure la colonne id dans la liste des colonnes que vous souhaitez récupérer.
Dans Laravel 5.6, vous pouvez appeler un champ spécifique comme celui-ci
$users = App\Book::with('author:id,name')->get();
Dans votre modèle Post
:
public function userWithName()
{
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}
Maintenant, vous pouvez utiliser $post->userWithName
Notez que si vous n'avez besoin que d'une colonne de la table, utiliser 'lists' est plutôt agréable. Dans mon cas, je récupère les articles préférés d'un utilisateur, mais je ne veux que l'identifiant de l'article:
$favourites = $user->favourites->lists('id');
Retourne un tableau d'identifiants, par exemple:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
Je suis tombé sur ce problème, mais avec une deuxième couche d'objets liés. La réponse de @Awais Qarni résiste à l'inclusion de la clé étrangère appropriée dans l'instruction select imbriquée. Tout comme un identifiant est requis dans la première instruction select imbriquée pour référencer le modèle associé, la clé étrangère doit référencer le deuxième degré de modèles associés; dans cet exemple, le modèle d'entreprise.
Post::with(['user' => function ($query) {
$query->select('id','company_id', 'username');
}, 'user.company' => function ($query) {
$query->select('id', 'name');
}])->get();
De plus, si vous souhaitez sélectionner des colonnes spécifiques du modèle Post, vous devez inclure la colonne user_id dans l'instruction select afin de la référencer.
Post::with(['user' => function ($query) {
$query->select('id', 'username');
}])
->select('title', 'content', 'user_id')
->get();
EmployeeGatePassStatus::with('user:id,name')->get();
Comme vous définissez la relation dans le modèle, essayez ceci
$postdata = Post::with('user')->get();
$posdata = $postdata->map(function(posts){
return collection([
............
...........
'user' => $posts->user->map(function($user){
'id' => $user->id,
'username' => $user->username
})
])
})
Essayez avec des conditions.
$id = 1;
Post::with(array('user'=>function($query) use ($id){
$query->where('id','=',$id);
$query->select('id','username');
}))->get();
Vous pouvez maintenant utiliser la méthode pluck
sur une instance Collection
:
Cela renverra uniquement l'attribut uuid
du Post model
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
all: [
"1",
"2",
"3",
],
}