前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Laravel 多态关系的表单验证

Laravel 多态关系的表单验证

作者头像
overtrue
发布2018-07-05 15:05:55
2.1K0
发布2018-07-05 15:05:55
举报

相信大家使用 Laravel 开发应用的时候都会有评论模块吧,而且我们通常将该模块设计为多态关系(如果你对这个关系还不明白的话,请赶紧打开 Laravel 文档数据库关系章节复习一遍吧!)。

先看看我们的数据库结构:

代码语言:javascript
复制
id
commentable_id
commentable_type
body

那么遇到一个问题,如果写入数据呢?一般来讲有两种方式,而我们通常用的一种是从父模型使用关系写入,比如我们有一个 App\Thread 类,它里面对评论的关系是这样的:

代码语言:javascript
复制
class Thread 
{
    public function comments() {
            $this->morphToMany(Comment::class, 'commentable');
    }
}

然后我们的写入评论时通常是这样的:

代码语言:javascript
复制
$comment = new Comment(['body' => 'hello']);
$thread->comments()->save($comment);

或者这样最直接的方式:

代码语言:javascript
复制
$comment = Comment::create([
        'commentable_type' => 'App\\Thread',
        'commentable_id' => 1,
        'body' => 'Very Good!',
]);

其实不管哪一种,我们都少不了表单验证,而且无论使用任何一种我们都得需要传入两个关键参数: 类型与 id,那就涉及到一个问题,如何验证呢?

你可能会写成这样:

代码语言:javascript
复制
public function store(Request $request)
{
        $this->validate($request, [
            'commentable_type' => 'required|string',
            'commentable_id' => 'required|integer',
        ]);

        $model = resolve($request->get('commentable_type'))
                ->find($request->get('commentable_id'));

        if (!$model) {
            abort(403, '目标对象不存在!');
        }

        $comment = new Comment(['body' => $request->get('body')]);

        return new CommentResource($model->comments()->save($comment));
}

这样写感觉很复杂且不直观对吧?那么我们现在介绍一种拓展验证规则的写法:

首先我们在 AppServiceProvider 中注册一个验证规则 poly_exists

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

      try {
          return !empty(resolve($objectType)->find($value));
      } catch (\Exception $e) {
          return false;
      }
})

这样我们就可以把控制器里的写法简化成这样:

代码语言:javascript
复制
public function store(Request $request)
{
        $this->validate($request, [
           'commentable_id' => 'required|poly_exists:commentable_type',
      ]);

        return new CommentResource(new Comment($request->all()));
}

怎么样?是不是简单很多,而且这样验证规则还能重用在其它同类多态关系的地方哦。

这样就结束了么?没有!

我们上面的拓展验证规则的写法没有感觉有些粗暴么?是时候规范一下了。

我们应该把所有的验证器都独立成一个类,放到 App\Validators 空间下,比如上面的关系验证我们可以叫做 App\Validators\PolyExistsValidator

代码语言:javascript
复制
<?php
namespace App\Validators;

/**
 * Class PolyExistsValidator
 */
class PolyExistsValidator
{
    public function validate($attribute, $value, $parameters, $validator)
    {
        if (!$objectType = array_get($validator->getData(), $parameters[0], false)) {
            return false;
        }

        try {
            return !empty(resolve($objectType)->find($value));
        } catch (\Exception $e) {
            \Log::error($e->getMessage());
            return false;
        }
    }
}

然后我们在 AppServiceProvider 中添加一个属性 $validators 并且添加一个方法 registerValidators

代码语言:javascript
复制
protected $validators = [
        'poly_exists' => \App\Validators\PolyExistsValidator::class,
];



/**
 * Register validators.
 */
protected function registerValidators()
{
    foreach ($this->validators as $rule => $validator) {
        Validator::extend($rule, "{$validator}@validate");
    }
}

public function boot()
{
    $this->registerValidators(); 
}

在 boot 方法中我们统一注册了 $validators里的验证规则,这样一来,添加删除一个规则都会科学清晰很多了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 假装我会写代码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档