Skip to content
Kevin Upton edited this page Nov 30, 2017 · 14 revisions

This model is one of the cooler classes within the Ethereal package.

How it Works

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.

The Database

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.

The Models

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.

Usage

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.

Saving and Creating

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();

Variables

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
Clone this wiki locally