A simple polymorphic relationship in laravel

push notification with laravel

A simple polymorphic relationship can be used when you have an entity that can belong to either one entity or to another.

So, here’s our first example. Imagine that you are creating an e-commerce application. You will be able to upload some photos: either for a product, a category, or a blog post.

This means that we will have, first of all, four separate entities:

  • Photo
  • Product
  • Category
  • Post

Now, let’s prepare some code skeletons as follows:

  // file: app/Photo.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Photo extends Model {

    //

  }

  // file: app/Product.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Product extends Model {

    //

  }

  // file: app/Category.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Category extends Model {

    //

  }

  // file: app/Post.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Post extends Model {

    //

  }

Now, you can define this polymorphic relationship using the morphTo() and morphMany() methods.

  • The morphTo() method is used by the class that is related to all the other classes.
  • The morphMany() method is called by the owner classes.

So, let’s edit our models like this:

  // file: app/Photo.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Photo extends Model {

    public function imageable()
    {
      return $this->morphTo();
    }

  }

  // file: app/Product.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Product extends Model {

    public function photos()
    {
      return $this->morphMany('Photo', 'imageable');
    }

  }

  // file: app/Category.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Category extends Model {

    public function photos()
    {
      return $this->morphMany('Photo', 'imageable');
    }

  }

  // file: app/Post.php
  <?php namespace App;

  use IlluminateDatabaseEloquentModel;

  class Post extends Model {

    public function photos()
    {
      return $this->morphMany('Photo', 'imageable');
    }

  }

Done! Wait, wait. What’s that imageable that is used both as a name for the method and as a string parameter? It is a name you can choose for yourself: however, take a look at the table structure I have used, to understand.

  products
      id - integer
      name - string

  categories
      id - integer
      name - string

  posts
      id - integer
      name - string

  photos
      id - integer
      path - string
      imageable_id - integer
      imageable_type - string

The photos table has two special fields: imageable_id and imageable_type. A simple external key, the only difference is that, for the elements in this photos table, you can count owners of different types.

So, in imageable_id, you will put the owner ID and in imageable_type, the owner class name!

If a photo belongs to a product, you will see Product in the imageable_type column, then Category if the photo belongs to a category, and so on.

Obviously, working with this relationship is very simple. Here’s an example:

  // getting a sample product...
  $product = AppProduct::find(3);

  foreach($product->photos as $photo)
  {
    // working with photos here...
  }

This applies for every other entity!

  // getting a sample category
  $category = AppCategory::find(42);

  foreach($category->photos as $photo)
  {
    // working with category photos here...
  }

Finally, you can also reverse things. If you have a photo and want to know who the owner is, all you have to do is:

  $photo = AppPhoto::find(23);

  // getting the owner...
  var_dump($photo->imageable);

No matter what the owner’s class is, Eloquent will automatically resolve the instance and return it to you. If the owner is a blog post, you’ll get the blog post. Easy!

About the author

Deven Rathore

Deven Rathore

I'm Deven Rathore, a multidisciplinary & self-taught designer with 3 years of experience. I'm passionate about technology, music, coffee, traveling and everything visually stimulating. Constantly learning and experiencing new things.

Pin It on Pinterest

Shares