1

How can I eager load only specific columns from a polymorphic relationship?

I have a people table that morphs to users and bots, from where I only need to load first_name and last_name for a specific query.

I've tried this solution with no luck, since it doesn't seem to apply for polymorphic relationships... it simply ignores the ->select() and loads everything as it should.

Any Ideas?

EDIT : Here is the relevant query

$school->load(array(
                'associationsTeachers' => function($q){
                    $q->with(array(
                            'person' => function($q2){
                                $q2->with(array(
                                    'account' => function($q3){
                                        $q3->select(array('id', 'first_name', 'last_name', 'person_id', 'account_id', 'account_type' ));
                                    }
                                ));
                            },
                    ));
                }
            ));

And here are the the relations

Person

table: 'people';
public function account(){
    return $this->morphTo();
}

User

table: 'users'
public function person(){
    return $this->morphOne('Person', 'account');
}

Bot

table: 'bots'
public function person(){
    return $this->morphOne('Person', 'account');
}
Community
  • 1
  • 1
clod986
  • 2,527
  • 6
  • 28
  • 52
  • i've been same problem.But i find https://github.com/laravel/framework/issues/2966. Author of Laravel say not support limiting the selects on those relations – masouk Sep 23 '17 at 04:18
  • You can do it now https://laravel.com/docs/9.x/eloquent-relationships#nested-eager-loading-morphto-relationships – Colin Claverie Oct 20 '22 at 14:40
  • Please review this answer to see if it helps https://stackoverflow.com/questions/58043886/select-specific-columns-on-eager-loading-polymorphic-relationships-laravel/76742334#76742334 the solution is to use constrain – Marianela Diaz Jul 22 '23 at 15:41

2 Answers2

2
ParentModel::with(['relationship' => function ($q) {
    $q->select('relationship_table.only_this', 'relationship_table.this_too', 'relationship_table.foreign_key');
}])->get();

This should work. Be careful to include the foreign key (and morph type, since you're using polymorphic relationship) since the query needs it to find the related models.

Edit:

I have also tried this on a polymorphic relationship (that I have set up in one of my projects) and it works as intended (returns only selected columns):

public function relationship()
{
    return $this->morphedByMany(\FullNS\RelationModel::class, 'pagable')
        ->select(['relation_table.id', 'relation_table.key]);
}

Edit 2:

Something like this should work. But it expects all the selected columns to be in the accounts table (which I guess is incorrect assumption). I don't know from your question which tables have which columns.

$school->load(['associationsTeachers' => function ($q) {
    $q->with(['person' => function ($q) {
        $q->with(['account' => function ($q) {
            $q->select('accounts.id', 'accounts.first_name', 'accounts.last_name', 'accounts.person_id', 'accounts.account_id', 'accounts.account_type');
        }]);
    })];
}]);
DevK
  • 9,597
  • 2
  • 26
  • 48
  • that's exactly what I've tried but it doesn't work. I've also put the morph keys as you suggested with no luck. I believe the problem derives from the fact that this is not considered as a join... – clod986 Jan 09 '17 at 15:31
  • @clod986 It's not performing a join. It's performing another query to fetch the associated results. But it should work if your relationships and models are set correctly. Post your models with relationships and the exact query you're trying to execute please. – DevK Jan 09 '17 at 15:35
  • @clod986 I've updated my answer. I've also tested both options and they both work fine. The issue has to be somewhere else. – DevK Jan 09 '17 at 15:46
  • I've updated my question. Please remember I'm on laravel 4.2 – clod986 Jan 09 '17 at 15:51
  • @clod986 Are you sure the relationships work (as in, you test 1 by 1 and they return what you expect them to return)? Another question then - where are all those columns saved (`'id', 'first_name', 'last_name', 'person_id', 'account_id', 'account_type'`)? – DevK Jan 09 '17 at 15:59
  • yes, everything works fine... I have a big project running and I was just trying to speed it up a little. The last two columns are on people, the others are on users and bots – clod986 Jan 09 '17 at 17:04
  • Work perfect. Thanks – MrEduar May 26 '21 at 19:46
1

Use this may help you

Person::with(["account" => function($query) {
   $query->select("accountable_id", "first_name",  "last_name");
 }])
Ali Yousefi
  • 472
  • 4
  • 11