Laravel Polymorphic Relations commentable_type validation

时间:2017-01-31 16:22:02

标签: php laravel eloquent

我使用REST API接收数据 数据模型与多态相关,类似于文档中的数据:
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

比方说,例如,API正在收到这条新评论:

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

如何验证收到的commentable_type是否存在且有效?

5 个答案:

答案 0 :(得分:4)

如果我正确理解了您的问题,那么您正在尝试验证多态关系的对象是否存在,对于给定的commentable_typecommentable_id

如果是这种情况,则没有现成的验证规则,但您可以创建一个。
根据{{​​3}},您可以执行以下操作:

首先,在服务提供商的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_type),然后解析对象并尝试查找给定ID($value)的记录。

请注意,要使其正常工作,commentable_type的值必须是完全限定的类名(例如App\Models\Post)。

希望这有帮助!

答案 1 :(得分:1)

包括变形图的更好方法:

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

答案 2 :(得分:1)

您可以在Request类中动态定义model_exists规则。像这样:

instance.setDate(new Date(2025, 09, 09));

答案 3 :(得分: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_idcommentable_type(假设您的关系已正确定义)。

附加检查

然后您可以通过模型events查看。您可以在保存到数据库之前对其进行验证。

答案 4 :(得分:0)

我的最终版本适用于验证类型和ID:

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