Drift

The personal blog of Phoenix-based developer Josh Janusch

Laravel's Morph Map

There's an exciting undocumented feature in Laravel that was introduced in 5.1 called morphMap. The Morph Map is an extension of the polymorphic relationships and an effort to make them easier to use. If you used them in pre-5.1, you'd see a record like this:

[
    "id" => 1,
    "comment" => "Hello world",
    "commentable_type" => "App\Models\Post",
    "commentable_id" => 5
]

The commentable_type included the full namespace for the associated record type, which had a few downsides:

  1. If that namespace changes, you had to write a migration to change all the instances in your database
  2. Long namespaces (such as App\Models\Customers\Projects\Bids\BidInvitation) means that you have to set a long max length on the column
  3. It's difficult to remember the full namespace
  4. It's best practice if the client doesn't know full namespaces

5.1 thankfully addressed this via pull request #9891, which added the Relation::morphMap() method. That method defines a mapping of names to class paths globally. You do this with:

Relation::morphMap([
    'post' => App\Models\Post::class,
    'video' => App\Models\Video::class,
    'user' => App\Models\User::class,
]);

That will allow you to use post instead of App\Models\Post in your database and will automatically map it when setting up the relationships within your Eloquent model. The best place to define that is in a service provider; I recently called it in AppServiceProvider. So now, you would instead add this record

[
    "id" => 1,
    "comment" => "Hello world",
    "commentable_type" => "post",
    "commentable_id" => 5
]

and it would behave in the exact same manner as the previous example does. This feature is completely undocumented right now with no clear indication why. I highly recommend using it and avoid writing your own implementation as we were forced to do on a 5.0 project.