Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

pickab00's avatar

Order by on polymorphic relationship

I have a polymorphic relationship (requests - requestable) which I want to do an order by the morph class.

Here is what my current implementation looks like:

// Model: Request
// Table: requests
// Morph: requestable_type, requestable_id

public function requestable()
    {
        return $this->morphTo();
    }


// Model: MaintenanceRequest
// Table: maintenance_requests

public function request()
    {
        return $this->morphOne(Request::class, 'requestable');
    }


// Model: HousekeepingRequest
// Table: housekeeping_requests

public function request()
    {
        return $this->morphOne(Request::class, 'requestable');
    }

Both the maintenance request and housekeeping request has a column named ticket. So when querying, how can I order by the requestable relationships ticket?

What I have tried:

$query = $this->model->newQuery(); // model being Request
$query->with(['requestable' => function($q) {
    $q->orderBy('ticket', 'desc'); // asc or desc comes from SPA
}]);

This does not seem to work. I am not sure how a join on this would look like since I want to order by all requestable classes instead of one specific class. What I mean is I don't want to run the order by for specifically MaintenanceRequest or HousekeepingRequest but can I do order by the ticket for both the models? If so, what is the approach?

0 likes
5 replies
kevinbui's avatar
kevinbui
Best Answer
Level 41

I have resolved a quite similar issue before, pls have a look at this thread.

So you can join the requests table with maintenance_requests and housekeeping_requests, then order by the ticket column.

Let me know if you need further help, or a detailed database query.

1 like
pickab00's avatar

@kevinbui Many thanks. This is just what I needed. Now I am running in to a bit of a performance issue here. I am trying to run this on 4 models and I have 200k records for sampling. It takes about 1.5 seconds to order with the query (same as the answer given)

pickab00's avatar

@kevinbui Another question is, when I do

WHEN purchases.id IS NOT NULL then purchases.processed_at
WHEN excess_stocks.id IS NOT NULL then excess_stocks.processed_at

on multiple, isn't it taking only the first case if its not null and ignoring the rest?

pickab00's avatar

@kevinbui according to the investigation, the query is slow because of the order by. it takes about 1 second to execute the query and that's 200k records which isn't much. How can I improve this?

kevinbui's avatar

@pickab00 regarding your first question, yes, and there will be only one condition to be true.

About your 2nd question, the performance one, you might want to try adding indices for the ticket column in both tables.

Please or to participate in this conversation.