Laravel多态关系commentable_type验证

idv4meu8  于 2023-11-20  发布在  其他
关注(0)|答案(6)|浏览(107)

我使用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是否存在且有效?

beq87vna

beq87vna1#

如果我正确地理解了你的问题,你试图验证多态关系的对象存在,对于给定的commentable_typecommentable_id
如果是这种情况,则没有现有的验证规则来执行此操作,但您可以创建一个。
根据文档,以下是您可以做的事情:
首先,在服务提供者的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)。
希望这对你有帮助!

eeq64g8w

eeq64g8w2#

更好的方法,包括变形图:

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

字符串

0sgqnhkj

0sgqnhkj3#

你可以在Request类中动态定义一个model_exists规则。类似这样:

public function rules()
{
    $polymorphExistsRule = '';
    if ($this->has('commentable_type')) {
        $polymorphExistsRule .= '|exists:' . $this->commentable_type . ',id';
    }

    return [
        'commentable_type' => 'required_with:commentable_id',
        'commentable_id'   => 'required_with:commentable_type' . $polymorphExistsRule,
    ];
}

字符串

vdgimpew

vdgimpew4#

编辑

我可能第一次误解了。如果你想检查保存在commentable_type中的模型是否存在,你可以这样做:

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

字符串
根据你的需要,你可以对它的inheritance进行额外的检查(例如,它扩展了类Model),或者其他任何真正适合你的需要的东西。

编辑2

如果我是你,我会这样做。我会将属性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)。
确保正确性的最简单方法是始终通过关系保存它。例如:

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


这将自动正确设置commentable_idcommentable_type(假设您的关系定义正确)。

额外检查

除此之外,你可以检查模型事件。你可以在保存到数据库之前验证它。

xuo3flqw

xuo3flqw5#

我的最终版本用于验证类型和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));
});

字符串

xsuvu9jc

xsuvu9jc6#

你可以做一些事情:

/**
 * Store a new comment.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $request->validate([
        'body' => 'required',
        'commentable_id' => 'required|exists:' . $request->commentable_type . ',id',
    ]);
 
    // The comment is valid...
}

字符串

相关问题