I am building a CMS package for Laravel.
All of my models in this package are bound to, and resolved from, the IoC container so that they can be easily overwritten in any individual deployment of the package.
For non-polymorphic relationships, this has worked a charm.
For instance, a Page has many PageModules, so its relationship changed from:
// \Angel\Core\Page
public function modules()
{
return $this->hasMany('PageModule');
}
to:
// \Angel\Core\Page
public function modules()
{
return $this->hasMany(App::make('PageModule'));
}
But I haven't been able to figure out how to do the same thing with polymorphic relationships.
For instance, Menus contain MenuItems, and each MenuItem can be tied to a single other model, such as a Page or BlogPost.
To accomplish this the Laravel way, I've added the following relationship to MenuItem:
// \Angel\Core\MenuItem
public function linkable()
{
return $this->morphTo();
}
And this relationship to LinkableModel, which all models such as Page and BlogPost extend:
// \Angel\Core\LinkableModel
public function menuItem()
{
return $this->morphOne(App::make('MenuItem'), 'linkable');
}
And the menus_items
table (which MenuItems use) has these rows:
linkable_type | linkable_id
-------------------|--------------
\Angel\Core\Page | 11
\Angel\Core\Page | 4
This works great, but I need the linkable_type
to say 'Page' instead of '\Angel\Core\Page', and to be resolved from the IoC's 'Page' instead of being hard-coded to a particular namespaced class.
What I've Tried:
According to this question, it should be as easy as defining a $morphClass
property to the linkable() classes, like so:
// \Angel\Core\Page
protected $morphClass = 'Page';
But when I apply this, and change the menus_items
table to look like this:
linkable_type | linkable_id
---------------|--------------
Page | 11
Page | 4
...I simply get a Class 'Page' not found.
error whenever linkable() is called on MenuItem.
This is the exact line in Eloquent that throws the error.
So, I dug into Eloquent and thought I might be able to get away with something like this:
// \Angel\Core\MenuItem
public function linkable()
{
return $this->morphTo(null, App::make($this->linkable_type));
}
...this feels so close, but alas: Eloquent calls linkable() before it's filled the rest of the MenuItem's attributes / columns, so $this->linkable_type is null and therefore will not resolve anything from the IoC.
Thank you so much in advance for any guidance you might have!