2017-01-31 11 views
2

Я использую API REST для получения данных.
модель данных является полиморфным родственный, похожий на тот, по документации:
https://laravel.com/docs/5.4/eloquent-relationships#polymorphic-relationsLaravel Полиморфные отношения commentable_type validation

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 

Скажем, например, API получающего этот комментарий:

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

Как может Я проверяю, существует ли доступный commentable_type и действителен ли он?

ответ

0

Редактировать

я, возможно, уже поняли в первый раз. Если вы хотите, чтобы проверить, что модель сохраняется в commentable_type существует вы могли бы сделать что-то вроде этого:

$type = $comment->commentable_type; 
if(class_exists($type)) echo "it exists"; 

В зависимости от ваших потребностей вы можете сделать дополнительные проверки для его inheritance (например, что он расширяет класс Model). Или что-нибудь еще, что действительно соответствует вашим потребностям.

Edit2

Это то, что я буду делать, если я вам. Я бы добавил свойство protected $allRelations к вашей модели Comment и вручную установил все отношения. Затем создайте некоторые вспомогательные модели, чтобы проверить, находится ли он в массиве.

Простой пример:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Comment extends Model 
{ 
    // .. 

    protected $allRelations= [ 
     'posts' => '\App\Post', 
     'videos' => '\App\Video', 
    ]; 

    public static function validateRelationNs($ns) { 
     return in_array($ns, $this->allRelations); 
    } 

    public static function validateRelationName($name) { 
     return array_key_exists($name, $this->allRelations); 
    } 

    // ... 
} 

Старый ответ:

Laravel ожидает полное имя пространства имен модели для колонок полиморфных типа (в вашем случае commentable_type должен быть \Full\Ns\Post, не posts).

Самый простой способ обеспечить правильность - это всегда сохранять его through the relationship. Например:

$post = Post::first(); 
$comment = new Comment($attributes); 
$post->comments()->save($comment). 

Это автоматически устанавливается как commentable_id и commentable_type правильно (если ваш relationsare правильно определен).

Дополнительная проверка

Другое то, что вы можете проверить с помощью модели events. Вы можете проверить его перед сохранением в базе данных.

+0

Я думаю, что эти данные должны быть проверены, прежде чем пытаться вставить в базе данных. Как-то все модели, связанные с моделью комментариев, на этапе валидации. – random425

+0

О, так вы хотите проверить, действительно ли модель существует после получения json уже сохраненного комментария? Я неправильно понял первый раз. – devk

+0

Не совсем, я хочу проверить, существует ли модель и является ли она полиморфной, в данном случае модель комментариев. – random425

2

Если я правильно понимаю ваш вопрос, вы пытаетесь проверить, существует ли объект полиморфного отношения для данных commentable_type и commentable_id.

Если это так, для этого не существует действующего правила валидации, но вы можете его создать.
на основе the documentation, вот что вы можете сделать:

Во-первых, добавить новое правило в boot методе поставщика услуг (например, 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)); 
}); 

И это, как вы будете использовать это:

'commentable_id' => 'required|poly_exists:commentable_type 

Что правило делает это пытается и выбирает commentable тип из входных значений (на основе параметра, передаваемого по правилу, т.е. commentable_type в нашем случае), а затем разрешает объект и пытается найти запись для данного ID ($value).

Обратите внимание, что для этого, однако, значение commentable_type должно быть полным классом (например, App\Models\Post).

Надеюсь, это поможет!

+0

У меня был тот же самый вопрос, и я попытался использовать ваш фрагмент, но не смог заставить его работать, поэтому не уверен, что я сделал не так. Если я откажу от правила проверки, то, конечно, он отлично работает, но в тот момент, когда я добавляю его обратно в FormRequest, я получаю сообщение об ошибке «Поле комментариев для комментариев». – seekay

+0

@seekay, похоже, что он не находит поле 'commentable_id' на вашем входе. Можете ли вы показать мне пример запроса, который вы пытаетесь сделать? – osteel

+0

здесь [gist] (https://gist.github.com/chandank/f269f0860d4fd01459ce4997600ec10c) - Я думаю, причина в том, что я использую привязку маршрутной модели. Я думаю, что это сработает, если я включу в форму скрытое поле с 'commentable_id', но это кажется взломанным.Мысли/предложения? Я могу открыть отдельный вопрос, если это проще. – seekay

0

Моей окончательного варианта работа для типа проверки и идентификатора:

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

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

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

Лучше подход, который включает в себя морфу карты:

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)); 
    });