Where you store that data is entirely up to you, if it makes sense to have it in a model/DB you can. or you can create your own simple courier class /factory whatever you need, with the rates hardcoded (not ideal) or loaded from a file, csv, json whatever.
so you could do
$packageWeight = 1.1;
$destination = 'b';
$courierRates = [
[ 'weight' => 1, 'cost' => 8.00, 'location' => 'a' ],
[ 'weight' => 1, 'cost' => 10.00, 'location' => 'b' ],
[ 'weight' => 2, 'cost' => 9.10, 'location' => 'a' ],
[ 'weight' => 2, 'cost' => 11.10, 'location' => 'b' ],
...
];
$rate = collect($courierRates)
->filter(fn($rate) => $rate['location'] == $destination)
->sortBy('weight') // optional: ensures the rates are in weight order
->first(fn($rate) => $rate['weight'] >= $packageWeight);
$rate['cost']; // = 11.10
or if you've got eloquent models for the couriers, rates & locations you could do something like this.
$shippingCosts = Courier::with('rates.location')->get()
->mapWithKeys(function($courier) use ($destination, $weight) {
return [
$courier->name => $courier->rates
->filter(fn($rate) => $rate->location->name == $destination)
->sort('weight')
->first(fn($rate) => $rate->weigth >= $weight)->cost
];
});
$shippingCosts == [
'Courier A' => 3.00,
'Courier B' => 3.00,
'Courier C' => 3.00,
];
N.B. that's also a pretty bad eloquent query you'd probably want to query / scope it by the location so you only load the relevant rates not all of them if you have hundreds..
class Rate extends Model
{
protected $fillable = [
'courier_id',
'weight',
'cost',
'location_id',
];
public function location()
{
return $this->belongsTo(Location::class);
}
public function courier()
{
return $this->belongsTo(Courier::class);
}
}
class Courier extends Model
{
public function rates()
{
return $this->hasMany(Rate::class);
}
public function locations()
{
return $this->hasManyThrough(Location::class, Rate::class);
}
}
class Location extends Model
{
protected $fillable = [
'name',
];
}