Patrick_Finucane
Patrick_Finucane

Reputation: 755

Laravel 5 Read Only View Model with polymorphic Relationship

Sometimes we use MySql Views to organize related tables to make it easier to search and sort. For example if you have Posts with a Status, and a Source.

Post
    subject
    body
    source_id
    status_id

Status
    id
    label
    other_field

Source
    id
    label
    other_field


View
   create view read_only_posts as
   SELECT statuses.label as status, sources.label as source, posts.*
   from posts
   left join statuses on statuses.id = posts.status_id
   left join sources on sources.id = posts.source_id

Then we have the Post model and an extra model:

// Post.php
class Post extends Model
{
    //
}

// ReadOnlyPost.php
class ReadOnlyPost extends Post
{
    protected $table = 'read_only_posts';
}

This is nice because now you can directly sort or filter on Status or Source as a string not the id's. You can also include the 'other_field'.

But we have a problem that I need help with. If you have a polymorphic many-to-many relationship on Posts, I can't get it to work on the read only version. For example if you have polymorphic tags:

// Post.php Model
public function tags()
{
    return $this->morphToMany(Tag::class, 'taggable');
}

The problem is when you filter a post (using the read only model) with a specific tag you get sql like this:

select count(*) as aggregate from read_only_posts where exists (select * from tags inner join taggables on tags.id = taggables.taggable_id where read_only_posts.id = taggables.taggable_type and taggables.taggable_type = 'read_only_posts' and label = 'test')

As you can see the problem is the taggables.taggable_type = 'read_only_posts'.

I can't find a way to override the morph type for a model. (I am on laravel 5.4 and the MorphClass isn't there anymore). The morph map is an associative array so you can't do this:

// AppServiceProvider
public function boot()
{
    Relation::morphMap([
        'posts' => Post::class,
        'posts' => ReadOnlyPost::class, <--- Can't do this

My stupid fix is when I attach a tag to a post I also attach it to ready_only_posts, which is kind of a mess.

Anyone else uses Views for read only models? Anyone have a better way to overriding the many to many polymorphic type for a specific model?

Upvotes: 3

Views: 538

Answers (1)

Chris Phillips
Chris Phillips

Reputation: 673

Looking at the code, I believe this might work.

class ReadOnlyPost extends Posts
{
    public function getMorphClass() {
         return 'posts';
    }
}

In theory you should need to have the Posts model/table listed in the morph map, since the system will auto generate the type of "posts" for it based on naming.

Upvotes: 3

Related Questions