ninetysix's avatar

What does morphTo actually do?

Hi,

Sorry if this has already been posted I am new to the forums!

I have recently got into package development, all be it basic package development but I've taken a step out into open source!

I have been referencing other packages in order to keep in line with standards and to actually help me along the way.

I keep seeing morphTo in relationship models. I know about polymorphic relationships and is this related to that? I can't see anything in the Laravel documentation but I can see it in the Laravel API.

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

Above in as an example of this in action.

If someone could tell me what it does and why it's used as I actually feel like I need to use this for what I'm working on.

Thanks in advance!

0 likes
6 replies
manelgavalda's avatar

It retrieves the actual model related to your class with the boardable relation.

For example, if you have comments that can exists either in a post or in an image, you will have something like this:

class Image extends Model {
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}
class Post extends Model {
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}
class Comment extends Model {
    public function commentable()
    {
        return $this->morphTo();
    }

}

 $comment->commentable(); // You will get the Post or the Image that this comment is related to.
4 likes
ninetysix's avatar

@MANELGAVALDA - Thanks for the example, makes sense now.

In terms of the package, the developer in which is using the package will have to define the morphMany themselves if the package was to work that way?

manelgavalda's avatar
Level 50

@NINETYSIX - I think the recommended thing here is to create a trait so the developer will have an easy way to implement this relation.

You can take for example this spatie package used to handle user roles: https://github.com/spatie/laravel-permission

He uses the HasRoles trait in this case in order to define the polymorphic relationships: https://github.com/spatie/laravel-permission/blob/master/src/Traits/HasRoles.php

In the trait you can see this:

    /**
     * A model may have multiple roles.
     */
    public function roles(): MorphToMany
    {
        return $this->morphToMany(
            config('permission.models.role'),
            'model',
            config('permission.table_names.model_has_roles'),
            config('permission.column_names.model_morph_key'),
            'role_id'
        );
    }

So then the developer will have this relation available in his model just using the trait:

use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;

    // ...
}

Hope this helps you in order to develop the package.

7 likes
Digitalized's avatar

"MorphTo" is used to define the relationship from a one-to-one or one-to-many polymorphic table to whichever model or models it is linked to

https://laravel.com/docs/5.7/eloquent-relationships#one-to-many-polymorphic-relations

For example, lets say you had an Address model

One or more models could link to the same addresses table / model, via an addresses relationship. eg.

class User {

    public function addresses()
    {
        return $this->morphMany('App\Address', 'addressable');
    }

}


class Provider {
    
    public function addresses()
    {
        return $this->morphMany('App\Address', 'addressable');
    }

}

// Conversely, the address model can link back to the User or Provider model (the polymorphic part) 

class Address {

    // This could link to either a provider or a user!
    public function addressable()
    {
        return $this->morphTo();
    }

}

This means you can have a single addresses table for both users or providers, rather than one address table for users, one for providers, etc.

Hope that makes sense

4 likes
ninetysix's avatar

@MANELGAVALDA - That's brilliant. You've really helped me out, I knew about traits but didn't know if this would be the right scenario to use them in so thank you for clarifying that.

2 likes

Please or to participate in this conversation.