Fetch specific fields on a hasMany relation

2020-06-03 01:24发布

问题:

I have a hasMany relation function like this:

public function articles()
{
    return $this->hasMany('App\Article');
}

And use it like this:

$data = \App\User::with('articles')->get();

I don't have any problems with it, since it's returning the expected data. Something like this:

{
"id": 1,
"name": "Jhon",
"lastname": "Doe",
"articles": [
    {
        "id": 1,
        "title": "Article 1",
        "status": "published",
        "published_at": "2015-04-30"
    },
    {
        "id": 2,
        "title": "Article 2",
        "status": "draft",
        "published_at": null
    }
 ]
}

What I am trying to achieve but I still can't it's to fetch just a subset of the relation's fields to obtain this:

{
"id": 1,
"name": "Jhon",
"lastname": "Doe",
"articles": [
    {
        "id": 1,
        "title": "Article 1"
    },
    {
        "id": 2,
        "title": "Article 2"
    }
  ]
}

My intention is to find a way to specify the subset of fields in the Model's function instead of iterating the returning collection and unset the unwanted fields.

Is this possible?

回答1:

You've got a couple options:

  1. Modify the relationship query when using it. The with() method can accept an array of key/value pairs where the key is the name of the relationship and the value is a Closure that modifies the relationship query.

    $data = \App\User::with(['articles' => function($query) {
        // user_id is required here*
        $query->select(['id', 'title', 'user_id']);
    }])->get();
    
  2. Create a new relationship that contains the fields you want.

    public function articleTitles() {
        // user_id is required here*
        return $this->hasMany('App\Article')->select(['id', 'title', 'user_id']);
    }
    
    $data = \App\User::with('articleTitles')->get();
    
  3. If you're only concerned about the array/json output, you can modify the App\Article model to only display the id and title when converted to an array.

    class Article extends Model {
        protected $visible = ['id', 'title'];
    }
    

What you choose depends on what you need.


*NB: For options 1 and 2 above, the foreign key (user_id) must be selected so that Laravel knows how to link the models together when building the relationships.



回答2:

$data = \App\User::with('articles:id,title,user_id')->get();

// user_id is important in hasmay relationships