web-dev-qa-db-fra.com

Obtenir des colonnes spécifiques à l'aide de la fonction "With ()" dans Laravel Eloquent

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?

123
Awais Qarni

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. *

254
Awais Qarni

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

60
user1669496

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.

49
Thijs

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.

37
Adam

Dans Laravel 5.6, vous pouvez appeler un champ spécifique comme celui-ci

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

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

11
Duy Hoang

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
)
3
omar j

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();
2
jwarshaw
EmployeeGatePassStatus::with('user:id,name')->get();
0
kush

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

            ])
        })
0
anik islam Shojib

Essayez avec des conditions.

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

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",
     ],
   }
0
Giovanni Far