Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Polymorphic Relations commentable_type validation

I'm using a REST API to receive the data.
The data model is polymorphic related, similar to the one on the documentation:
https://laravel.com/docs/5.4/eloquent-relationships#polymorphic-relations

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

Let's say, for example, the API is receiving this new comment:

{
    "body": "This a test comment",
    "commentable_type": "posts",
    "commentable_id": "1"
}

How can I validate if the received commentable_type exists and is valid?

like image 413
random425 Avatar asked Jan 31 '17 16:01

random425


People also ask

What is polymorphic relationship in laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.

What is MorphTo in laravel?

"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.

What is confirmed in laravel validation?

confirmed. The field under validation must have a matching field of foo_confirmation . For example, if the field under validation is password , a matching password_confirmation field must be present in the input.


2 Answers

If I correctly understand your question, you are trying to validate that the object of the polymorphic relation exists, for the given commentable_type and commentable_id.

If that is the case, there is no existing validation rule to do so, but you can create one.
Based on the documentation, here is what you could do:

First, add the new rule in the boot method of a service provider (e.g. AppServiceProvider):

Validator::extend('poly_exists', function ($attribute, $value, $parameters, $validator) {
    if (!$objectType = array_get($validator->getData(), $parameters[0], false)) {
        return false;
    }

    return !empty(resolve($objectType)->find($value));
});

And this is how you would use it:

'commentable_id' => 'required|poly_exists:commentable_type

What the rule does is it tries and fetches the commentable type from the input values (based on the parameter passed on to the rule, i.e. commentable_type in our case), and then resolves the object and tries to find a record for the given ID ($value).

Please note that for this to work however, the value of commentable_type must be the fully qualified class name (e.g. App\Models\Post).

Hope this helps!

like image 147
osteel Avatar answered Oct 02 '22 13:10

osteel


Better approach that includes morphs map:

    Validator::extend('poly_exists', function ($attribute, $value, $parameters, $validator) {
        if (! $type = array_get($validator->getData(), $parameters[0], false)) {
            return false;
        }

        if (Relation::getMorphedModel($type)) {
            $type = Relation::getMorphedModel($type);
        }

        if (! class_exists($type)) {
            return false;
        }

        return ! empty(resolve($type)->find($value));
    });
like image 42
Vedmant Avatar answered Oct 02 '22 11:10

Vedmant