美高梅网址注册-澳门mgm4858集团登录网址
做最好的网站
来自 澳门mgm4858集团登录网址 2020-03-01 01:41 的文章
当前位置: 美高梅网址注册 > 澳门mgm4858集团登录网址 > 正文

extend 来扩展一个自定义的规则,验证器怎么创建

验证器怎么创建的,谁创建的

 

Laravel 5.5 将提供一个全新的自定义验证规则的对象,以作为原来的 Validator::extend 方法的替代。

Laravel 文档调用验证器,除了通过控制器,还有就是通过Facades的方式创建验证器对象。Validator::make。

1、简介

Laravel中的契约是指框架提供的一系列定义核心服务的接口。 例如 ,IlluminateContractsQueueQueue契约定义了队列任务需要实现的方法,IlluminateContractsMailMailer契约定义了发送邮件所需要实现的方法。

每一个契约都有框架提供的相应实现。例如,Laravel为队列提供了多个驱动的实现,邮件则由 SwiftMailer驱动 实现 。

所有Laravel契约都有其对应的GitHub库,这为所有有效的契约提供了快速入门指南,同时也可以作为独立、解耦的包被包开发者使用。

Laravel 5.5 将提供一个全新的自定义验证规则的对象,以作为原来的 Validator::extend 方法的替代。。很多时候我们会直接用正则表达式来处理这种特殊的验证,也有时候我们会选择用 Validator::extend 来扩展一个自定义的规则。但在 Laravel 5.5 版本中,我们有了新的手段,只要定义一个实现 IlluminateContractsValidationRule 接口的类即可实现自定义的验证规则,并可以直接使用。

config/app.php 中注册了'Validator' => IlluminateSupportFacadesValidator::class。

契约(Contracts) VS 门面(Facades)

Laravel门面为Laravel服务的使用提供了便捷方式——不再需要从服务容器中类型提示和契约 解析即可直接通过静态门面调用 。有些开发者喜欢这种便捷,不过也有开发者倾向于使用契约,他们喜欢定义明确的依赖。

注:大多数应用中,不管你使用门面还是契约,合适就好。不过,如果你是在构建一个扩展包,那么就应该使用契约,因为这在扩展包中更容易测试。

下面是一个简单的示例:

从上面可以看出,Validator的实际实现类是容器中的validator对象,那这个validator对象是哪个?namespace IlluminateFoundation;...class Application extends Container implements ApplicationContract, HttpKernelInterface{ ... public function registerCoreContainerAliases() { foreach ([ ... 'validator'=> [ IlluminateValidationFactory::class, IlluminateContractsValidationFactory::class ], ]) ... } ...}
2、何时使用契约

正如上面所讨论的,大多数情况下使用契约还是门面取决于个人或团队的喜好,契约和门面都可以用于创建强大的、测试友好的Laravel应用。只要你保持类的职责单一,你会发现使用契约和门面并没有什么实质性的差别。

但是,对契约你可能还是有些疑问。例如,为什么要全部使用接口?使用接口是不是更复杂?下面让我们从两个方面来扒一扒为什么使用接口:松耦合和简单。

use IlluminateContractsValidationRule;class IsOddValidationRule implements Rule{ public function passes { return ; } public function message() { return ':attribute 必须是奇数'; }}

可以看出,最终创建验证器是通过实现IlluminateContractsValidationFactory接口的IlluminateValidationFactory类创建的。再来看看,这个工厂类怎么创建实际的验证器的。

松耦合

首先,让我们看看一些缓存实现的紧耦合代码:

<?php

namespace AppOrders;

class Repository{
    /**
     * 缓存
     */
    protected $cache;

    /**
     * 创建一个新的Repository实例
     *
     * @param  SomePackageCacheMemcached  $cache
     * @return void
     */
    public function __construct(SomePackageCacheMemcached $cache)
    {
        $this->cache = $cache;
    }

    /**
     * 通过ID获取订单
     *
     * @param  int  $id
     * @return Order
     */
    public function find($id)
    {
        if ($this->cache->has($id))    {
            //
        }
    }
}

在这个类中,代码和给定缓存实现紧密耦合,由于我们基于一个来自包的具体的缓存类,如果包的API变了,那么相应的,我们的代码必须做修改。

类似的,如果我们想要替换底层的缓存技术(Memcached)为别的技术实现(Redis),我们将再一次不得不修改我们的代码库。我们的代码库应该并不知道谁提供的数据或者数据是怎么提供的。

我们可以基于一种简单的、与提供者无关的接口来优化我们的代码,从而替代上述那种实现:

<?php

namespace AppOrders;

use IlluminateContractsCacheRepository as Cache;

class Repository{
    /**
     * 创建一个新的Repository实例
     *
     * @param  Cache  $cache
     * @return void
     */
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }
}

现在代码就不与任何特定提供者耦合,甚至与Laravel都是无关的。由于契约包不包含任何实现和依赖,你可以轻松的为给定契约编写可选实现代码,你可以随意替换缓存实现而不用去修改任何缓存消费代码。

以上代码定义了一个 IsOddValidationRule 的自定义验证类,在 Controller 中要使用这个验证类的话,可以这样写:

//IlluminateContractsValidationFactory 源码protected function resolve(array $data, array $rules, array $messages, array $customAttributes){ if (is_null { return new Validator( $this->translator, $data, $rules, $messages, $customAttributes ); } return call_user_func( $this->resolver, $this->translator, $data, $rules, $messages, $customAttributes );}
简单

当所有Laravel服务都统一在简单接口中定义,很容易判断给定服务提供的功能。契约可以充当框架特性的简明文档。

此外,基于简单接口,代码也更容易理解和维护。在一个庞大而复杂的类中,与其追踪哪些方法是有效的,不如转向简单、干净的接口。

public function handlForm{ $this->validate($request, [ 'oddField' => [new IsOddValidationRule] ]);}

到这里,可以看出Laravel的验证器的创建都是通过特定的工厂类创建。

3、如何使用契约

那么,如何实现契约呢?这很简单。

Laravel中很多类都是通过服务容器进行解析,包括控制器,以及监听器、中间件、队列任务,甚至路由闭包。所以,要实现一个契约,需要在解析类的构造函数中类型提示这个契约接口。

例如,看看下面这个事件监听器:

<?php

namespace AppListeners;

use AppUser;
use AppEventsOrderWasPlaced;
use IlluminateContractsRedisDatabase;

class CacheOrderInformation
{
    /**
     * The Redis database implementation.
     */
    protected $redis;

    /**
     * Create a new event handler instance.
     *
     * @param  Database  $redis
     * @return void
     */
    public function __construct(Database $redis)
    {
        $this->redis = $redis;
    }

    /**
     * Handle the event.
     *
     * @param  OrderWasPlaced  $event
     * @return void
     */
    public function handle(OrderWasPlaced $event)
    {
        //
    }
}

事件监听器被解析的时候,服务容器会读取构造函数中的类型提示,并注入适当的值。要学习更多关于服务容器的注册细节,参考其文档。

同样的效果,也可以通过匿名函数来实现:

如果需要自定义验证器类(比如我需要把5.8的一些新功能迁移到5.5的版本上),有两种方式:

4、契约列表

下面是Laravel契约列表,以及其对应的“门面”:

Contract
References Facade

IlluminateContractsAuthFactory
Auth

IlluminateContractsAuthPasswordBroker
Password

IlluminateContractsBusDispatcher
Bus

IlluminateContractsBroadcastingBroadcaster

IlluminateContractsCacheRepository
Cache

IlluminateContractsCacheFactory
Cache::driver()

IlluminateContractsConfigRepository
Config

IlluminateContractsContainerContainer
App

IlluminateContractsCookieFactory
Cookie

IlluminateContractsCookieQueueingFactory
Cookie::queue()

IlluminateContractsEncryptionEncrypter
Crypt

IlluminateContractsEventsDispatcher
Event

IlluminateContractsFilesystemCloud

IlluminateContractsFilesystemFactory
File

IlluminateContractsFilesystemFilesystem
File

IlluminateContractsFoundationApplication
App

IlluminateContractsHashingHasher
Hash

IlluminateContractsLoggingLog
Log

IlluminateContractsMailMailQueue
Mail::queue()

IlluminateContractsMailMailer
Mail

IlluminateContractsQueueFactory
Queue::driver()

IlluminateContractsQueueQueue
Queue

IlluminateContractsRedisDatabase
Redis

IlluminateContractsRoutingRegistrar
Route

IlluminateContractsRoutingResponseFactory
Response

IlluminateContractsRoutingUrlGenerator
URL

IlluminateContractsSupportArrayable

IlluminateContractsSupportJsonable

IlluminateContractsSupportRenderable

IlluminateContractsValidationFactory
Validator::make()

IlluminateContractsValidationValidator

IlluminateContractsViewFactory
View::make()

IlluminateContractsViewView

public function handleForm{ $this->validate($request, [ 'oddField' => [function($attributes, $value, $fail) { if  { $fail; } }] ]);}

一,创建一个自定义的工厂类。然后在AppServiceProvider中重新绑定新的验证器工厂创建类;

在验证的表单项为空值或者不存在的时候,对应的自定义验证规则不会执行。这个与系统自带的验证规则的逻辑是一致的。如果你希望你的自定义验证规则,即使是在对应的表单项为空值时也被执行的话,那么只要把继承的接口从 rule 改成 ImplicitRule 即可:

二,AppServiceProvider中通过resolver方法设置工厂类的resolver属性,接管验证器的实例化,例如:

class IsOddValidationRule implements ImplicitRule{ ...}
Validator::resolver(function($translator, $data, $rules, $messages, $customAttributes){ return new ExtendValidator($translator, $data, $rules, $messages, $customAttributes);});

采用 Laravel 5.5 新增的自定义验证类,可以更好地管理大量的自定义验证规则,而且在 PHPStorm 之类的 IDE 中,从验证代码里快速跳转到对应的验证类的代码也会更方便。毕竟采用 Validator::extend 的话,你只能通过搜索对应验证类名称的字符串来找到规则定义的源代码。

如何自定义验证规则

匿名函数的自定义验证规则在一次性的简单验证逻辑中用起来确实会很方便,或者是在编码过程中快速测试验证逻辑也很实用。但是总的来说,还是建议采用更具组织性和可读性的自定义验证类。最佳方法是在编写 Controller 的过程中用匿名函数快速验证自定义规则,然后再把它移到自定义的验证类对象中。

本文由美高梅网址注册发布于澳门mgm4858集团登录网址,转载请注明出处:extend 来扩展一个自定义的规则,验证器怎么创建

关键词: