Using one table for many similar models in Laravel
In one project we have several models that are identical schemas with a similar usage that we wanted to keep in one table to make maintenance easier. They are basically a value list with the model name being the 'type' of the list. An example might be product colors or t-shirt sizes.
Here's how I made a base class that all these models could be extended from and just work 'TM'.
Our lists table has these fields (besides id etc):
- name
- label
- type
- description
- sort
The base class looks like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder ;
class ListBase extends Model
{
protected $table = 'lists';
protected static function booted()
{
/** 'type' will be the name of the derived class without the namespace e.g. 'Diet', or 'Condition' */
self::creating(function ($model) {
$model->type = class_basename(static::class);
});
self::addGlobalScope('list type scope', function(Builder $builder){
$builder->where('type', class_basename(static::class));
});
}
}
This adds some code that is automatically run when you create a new row using a derived class, that will use the derived class name for the type field. In addition, the global scope restricts the rows to ones that match the derived classes name.
A derived class looks like this:
<?php
namespace App\Models;
/**
* Class Color.
*
* @package namespace App\Models;
* @method static where(string $string, string $name)
*/
class Color extends ListBase
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name','label','description','sort'];
}
We can have many of these derived classes, and even though their data is all in the same table, they only 'see' their own rows.