To handle the relationship between shipments and multiple carriers, you can use a polymorphic relationship. This allows a model to belong to more than one other model on a single association. In your case, both company locations and carriers can be considered as "Stoppable" entities (i.e., places where the shipment can stop).
Here's how you can structure your models and database tables:
- Create a
stoppablestable that will act as a polymorphic relation. This table will store the type of stoppable (company or carrier) and its ID.
Schema::create('stoppables', function (Blueprint $table) {
$table->id();
$table->morphs('stoppable'); // This will add stoppable_type and stoppable_id columns
$table->timestamps();
});
- Create a
shipmentstable that will reference thestoppablestable for origin and destination.
Schema::create('shipments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('origin_id');
$table->unsignedBigInteger('destination_id');
$table->timestamps();
$table->foreign('origin_id')->references('id')->on('stoppables');
$table->foreign('destination_id')->references('id')->on('stoppables');
});
- Define the polymorphic relationship in your Eloquent models.
class Shipment extends Model
{
public function origin()
{
return $this->belongsTo(Stoppable::class, 'origin_id');
}
public function destination()
{
return $this->belongsTo(Stoppable::class, 'destination_id');
}
}
class Stoppable extends Model
{
public function stoppable()
{
return $this->morphTo();
}
}
class CompanyLocation extends Model
{
public function stoppables()
{
return $this->morphMany(Stoppable::class, 'stoppable');
}
}
class Carrier extends Model
{
public function stoppables()
{
return $this->morphMany(Stoppable::class, 'stoppable');
}
}
- When creating a shipment, you would first create a
Stoppablerecord for both the origin and destination, setting thestoppable_typeandstoppable_idto the appropriate values.
// Assuming you have a company location and a carrier instance
$companyLocation = CompanyLocation::find(1);
$carrier = Carrier::find(1);
// Create stoppables for origin and destination
$originStoppable = Stoppable::create([
'stoppable_type' => get_class($companyLocation),
'stoppable_id' => $companyLocation->id,
]);
$destinationStoppable = Stoppable::create([
'stoppable_type' => get_class($carrier),
'stoppable_id' => $carrier->id,
]);
// Create the shipment
$shipment = Shipment::create([
'origin_id' => $originStoppable->id,
'destination_id' => $destinationStoppable->id,
]);
- To retrieve the origin and destination for a shipment, you can simply use the
originanddestinationrelationships.
$shipment = Shipment::with(['origin.stoppable', 'destination.stoppable'])->find(1);
$origin = $shipment->origin->stoppable; // This will be an instance of CompanyLocation or Carrier
$destination = $shipment->destination->stoppable; // This will be an instance of CompanyLocation or Carrier
This setup allows you to have a flexible system where a shipment's origin and destination can be either a company location or a carrier, and you can easily extend it to include other types of stoppables in the future.