-
Notifications
You must be signed in to change notification settings - Fork 1
MorphModel
This model is one of the cooler classes within the Ethereal package.
The morphing ability within Laravel is quite cool. So what I have decided to do is extend that functionality even further to the Ethereal class. The best way to describe how it works it to give you an example scenario.
Take this database structure example
products
id - integer
name - string
category - string
price - double
morph_id - integer
morph_type - string
cars
id - integer
dealer - string
model - string
bike
id - integer
wheel_type - string
nb_gears - date
In this example, the product can morph into both a car and a bike. So it could represent something of a shop selling bikes and cars. What this structure does is it allows to take the columns which are common in both and move them into one table. Preventing duplication of structure, allowing for future modifications to be effortless.
So lets build the Ethereal models and relationships for them.
To begin with we need to start with the Product.php
class:
<?php namespace My\Example\Namespace;
use Kevupton\Ethereal\Models\Ethereal;
class Product extends Model
{
protected $fillable = array(
'name', 'category', 'price', 'morph_id', 'morph_type'
);
}
Take not of the public static $relationsData
. This is what makes the morph model work.
Now lets create Car.php
class:
<?php namespace My\Example\Namespace;
use Kevupton\Ethereal\Models\MorphModel;
class Car extends MorphModel
{
protected $morphBy = 'morph'; //the table column that it is morphed on example morph_id morph_type
protected $morphClass = Product::class; //the class of the parent table
// validation rules
// validating both the car and the product
public $rules = array(
'name' => 'required',
'category' => 'required',
'price' => 'required|numeric',
'dealer' => 'required',
'model' => 'required'
);
protected $fillable = array(
'dealer', 'model'
);
}
The main fields in this example are: $morphBy
and $morphClass
. These are the three properties that tell it where to link to.
Now that we have our models and database created, we can use the morph code to do anything a normal model could do, but have it apply to both parent and child.
Example:
$input = array(
'name' => 'test',
'price' => 10,
'category' => 'second-hand',
'dealer' => 'john\'s cars',
'model' => 'Ford Falcon'
);
// creates the two models
$car = Car::create($input);
$car->price = 10;
// saves the parent mode (because we only changed the parent model)
$car->save();
Accessing the attributes is as simple as requesting the name like a normal Laravel Model. However in this case, the MorphModel can also access the parent scope attributes, returning those if requested too. Example:
$car = Car::find($id);
// accessing parent attribute
$car->name;
// accessing local attribute
$car->dealer;
// setting a parent attribute
$car->name = 'tester';
If you want to access the parent directly, all you have to do is use the class name as snakecase. Example:
($car->product instanceof Product::class) == true
//or if the name of the class had more than one word:
($car->product_test instanceof ProductTest::class) == true