TL;DR: I need to know how I can retrieve models, but have them be sorted in a specific way based on related models.
I've got four related tables, three of which are used in a polymorphic relationship. Here's a simplified version of them:
checkcalls
id - integer
loadid - integer
type - string
stopid - integer
pickups
id - integer
loadid - integer
checkedin - boolean
loaded - boolean
pickuporder - integer
drops
id - integer
loadid - integer
checkedin - boolean
delivered - boolean
droporder - integer
checkcallstatus
id - integer
status - string
checkorder - integer
I've created a polymorphic relationship whereby the Checkcall is a child of either Pickup or Drop based on its type column. In addition, I've added a couple of accessors to unify the stops models further:
class Checkcall extends Model
{
public function stop(): MorphTo
{
return $this->morphTo(__FUNCTION__, "type", "stopid");
}
}
class Pickup extends Model
{
protected $appends = ["completed", "order"];
public function getCompletedAttribute()
{
return $this->attributes["loaded"];
}
public function getOrderAttribute()
{
return $this->attributes["pickuporder"];
}
public function checkcalls(): MorphMany
{
return $this->morphMany(Checkcall::class, "stop");
}
}
class Drop extends Model
{
protected $appends = ["completed", "order"];
public function getCompletedAttribute()
{
return $this->attributes["delivered"];
}
public function getOrderAttribute()
{
return $this->attributes["droporder"];
}
public function checkcalls(): MorphMany
{
return $this->morphMany(Checkcall::class, "stop");
}
}
And, of course, to make this polymorphic relationship work, I have to add a bit to App\Providers\AppServiceProvider.php:
public function boot(): void
{
Relation::enforceMorphMap([
'PC' => 'App\API\v2\Models\Pickup',
'LD' => 'App\API\v2\Models\Pickup',
'DC' => 'App\API\v2\Models\Drop',
'DE' => 'App\API\v2\Models\Drop',
]);
}
Those are four possible values for Checkcall's type column and the only ones we're concerned with here.
Now, I aim to retrieve a bunch of checkcalls for a given loadid, but they need to be in a specific order. There can be multiple pickups and multiple drops, but they should be in PC -> LD -> DC -> DE order, with all the pickup checkcalls first, then all the drop checkcalls second, and in order of the stops' pickuporder/droporder columns (which can be retrieved through their new order accessor).
I've got a start on it here, but the sortBy() just doesn't work as expected:
$checkcalls = Checkcall::with("stop")
->with("checkcallStatus")
->where("loadid", $loadID)
// ->orderBy("checkcallStatus.checkorder", "asc")
->get()
->sortBy([
function ($checkCall) {
return 'App\API\v2\Models\Pickup' === Relation::getMorphedModel($checkCall->stop->getMorphClass()) ? 0 : 1;
},
["stop.order", "asc"],
["checkcallStatus.checkorder", "asc"],
]);
The expected order of Checkcalls for a load that has 2 Pickups and 2 Drops should be as follows:
0 => Pickup #1, PC
1 => Pickup #1, LD
2 => Pickup #2, PC
3 => Pickup #2, LD
4 => Drop #1, DC
5 => Drop #1, DE
6 => Drop #2, DC
7 => Drop #2, DE
I do not know how to write an orderBy() or sortBy() in order to get this output. Can anyone please help me?
I apologize for the length and complexity of this request, but I did not know how else to explain the situation and illustrate the intended outcome. Please let me know if I need to clarify the situation further.