Ad

OrderBy On Laravel Polymorph One-to-one Relationship

- 1 answer

I have problem to sort results by polymorph's table relationship. Tried many ways, but results does not sort.

I have looked in many threads, and final result code that I have tried looks like this:

return \App\Models\Advert::with(['advertable' => function ($query) {
    $query->orderBy('rooms', 'DESC');
}])->get();

I want to sort all rows in "adverts" table by relationship's "room" column, but nothing happens.

My tables structure is:

enter image description here Laravel models looks like this:

<?php
// Main "adverts" polymorph table with advertable_id and advertable_type
class Advert extends \Illuminate\Database\Eloquent\Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
     */
    public function advertable()
    {
        return $this->morphTo();
    }
}

// "advert_flats" table
class Flat extends \Illuminate\Database\Eloquent\Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphOne
     */
    public function advert()
    {
        return $this->morphOne(\App\Models\Advert::class, 'advertable');
    }
}

// "advert_homes" table
class Home extends \Illuminate\Database\Eloquent\Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphOne
     */
    public function advert()
    {
        return $this->morphOne(\App\Models\Advert::class, 'advertable');
    }
}

UPDATE

If I dump SQL, then I see that this code does not event run into relationship

select * from `adverts` where `category_id` = 2 and `adverts`.`deleted_at` is null

Also I have tried to change whereHas function to work with polymorph relationships, as Laravel does not support whereHas with polymorph relations.

I have ran this code

return $model->whereHas('advertable', function ($q) {
   $q->orderBy('rooms', 'DESC');
}, '>=', 1, ['\App\Models\Flat']);

But it also does not sort results. I had to change Laravel builder to add support for polymorph tables.

UPDATE 2

I have resolved issue and implemented code by using example provided by @Sturm answer, after applying SortBy / SortByDesc I'm manually building LengthAwarePaginator.

But could this issue be resolved using Builder class, before calling ->get() method on my query ?

Ad

Answer

Here's something that will get you running, although I'll look for a moment more to see if there's a way to do it from Builder.

$sorted = $adverts->sortBy(function ($val, $key) {
    return $val->advertable->rooms;
}
Ad
source: stackoverflow.com
Ad