Laravel Model - How to manage a relationship with a lookup table (dynamic Enum)

Viewed 69

This is my first Laravel project. I'm using Laravel 8.54

The model for my project is a Batch of plants. A Batch can use different brand/type of bagged soil and this will be selected in a dropdown called "Soil Type".

This is a fairly finite list of options, but it may change per batch and there might end up being dozens of types that are added over time. The user would like a way to go to a settings area of the application and just add a new type to the list and that will appear in the "Soil Type" dropdown as soon as the new one is saved. They do not want to contact a developer every time they want to add a new type or edit an existing one.

So it seems a lookup table is the most logical choice here. I have read a few questions on SO about avoiding this using various methods of Enum representation, but it really seems to be the only way to satisfy the desire to have user-control over the list.

My question is, how would one go about defining the relationship between these two models (Batch and SoilType)? The only solution I can think of is simply adding a soil_type_id to the Batch model, which will be a foreign key to the SoilType model. And I will have to set this explicitly as an integer when I save/update a Batch.

But is there a nicer "Eloquent" way of doing something like this? None of the relationship options in the documentation seem to be a fit.

1 Answers

You get the idea right I think, Having a soil_type table is a good idea if you need to add / update / remove some over time.

Your table structuire should be something like this:

soil_type

  • id
  • name
  • ...

Batch

  • id
  • soil_type_id
  • ...

And for the models, a Batch belongsTo a SoilType. Also a SoilType hasMany Batch.

Also, for convenience you can add helper method to the SoilType model to get data formatted for a dropdown :

class Batch extends Model
{
    public function soilType()
    {
        return $this->belongsTo(SoilType::class);
    }
}
class SoilType extends Model
{
    public function batches()
    {
        return $this->hasMany(Batch::class);
    }

    public function getDropdownOptions()
    {   
        $options = [];
        foreach (static::all() as $type) {
            $options[$page->id] = $type->title . ' (' . $page->name . ')';
        }
        return $options;
    }
}
Related