What Are Polymorphic Relations and How Do We Use Them with Eloquent?

What Are Polymorphic Relations and How Do We Use Them with Eloquent?

While I was working on an application for a client, I had to implement a new module that entails the following:

  • Users ask for a budget quotation for a certain task.
  • Every task has a location.
  • Professionals can subscribe to different zones.
  • A zone can be a region or a city.

Now, let’s neglect the core application and try to implement this single module to see what we can achieve here.

laravel-l-slant

Scaffolding Application

I assume you have your development environment already set up. If not, you can check this Homestead Improved Quick Tip or just use the official Homestead Box.

Go ahead and create a new Laravel project using the Laravel installer or via Composer.

laravel new demo

Or

composer create-project --prefer-dist laravel/laravel demo

Edit your .env file with your database credentials.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead    
DB_PASSWORD=secret

Creating Migrations

Before creating our migrations, we should talk about Eloquent polymorphic relations and how they can benefit us in this case!
Polymorphism is often used when an object can have different forms (shapes). In our case, professional users subscribe to different zones and they get notified whenever a new job is posted in this area.

Lets start by creating the zones table.

php artisan make:model Zone --migration

This creates a migration file, but we do need to add a bit of code to it before it’s complete, as demonstrated by:

// database/migrations/2016_12_02_130436_create_zones_table.php

class CreateZonesTable extends Migration
{
    public function up()
    {
        Schema::create('zones', function (Blueprint $table) {
            $table->integer('user_id')->unsigned();

            $table->integer('zone_id')->unsigned();
            $table->string('zone_type');
        });
    }

    public function down()
    {
        Schema::dropIfExists('zones');
    }
}

Next, we create the cities and regions tables.

php artisan make:model Region --migration
// database/migrations/2016_12_02_130701_create_regions_table.php

class CreateRegionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('regions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
        });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('regions');
    }
}
php artisan make:model City --migration
// database/migrations/2016_12_02_130709_create_cities_table.php

class CreateCitiesTable extends Migration
{
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 255);
            $table->integer('postal_code')->unsigned();

            $table->integer('region_id')->unsigned()->nullable();
        });
    }

    public function down()
    {
        Schema::drop('cities');
    }
}

We could’ve achieved the same result by making a many to many relation with the cities and regions table. However, the zones table will act as an abstract class for the two other tables. The zone_id will hold an id for a city or a region and using the zone_type value Eloquent will decide which model instance to return.

Creating Models

Eloquent has the ability to guess the related table fields, but I decided not to use it just to explain how to map database fields to models. I will explain them as we go along!

Continue reading %What Are Polymorphic Relations and How Do We Use Them with Eloquent?%