亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Symfony2 ??? ??? / 驗證(Validation)

驗證(Validation)

驗證(Validation )是在Web程序中極為常見的任務(wù)。表單中輸入的數(shù)據(jù)需要驗證。寫入到數(shù)據(jù)庫或傳送到Web服務(wù)時,數(shù)據(jù)也需要驗證。

Symfony自帶了一個 Validator 組件,它讓校驗工作變得簡單和透明。該組件基于 JSR303 Bean校驗規(guī)范。

驗證的基礎(chǔ) ?

理解驗證的最好方法就是看它的實際應(yīng)用。在開始之前,假設(shè)你創(chuàng)建了一個原生php對象,它用在程序需要的某個地方:

// src/AppBundle/Entity/Author.phpnamespace AppBundle\Entity; class Author{
    public $name;}

目前為止,這只是一個為你的程序提供某些用途的普通類。驗證的目的就是要告訴你,對象中的數(shù)據(jù)是否有效。為此,你需要配置一個規(guī)則列表(稱為 constraints/約束 ),對象必須遵循之方能有效。這些規(guī)則可以通過多種不同的格式(YAML、XML、annotations或PHP)來指定。

比如,要保證屬性 $name 不為空,添加以下內(nèi)容:

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints\NotBlank; class Author{
    public $name;     public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('name', new NotBlank());
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <property name="name">
            <constraint name="NotBlank" />
        </property>
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    properties:
        name:
            - NotBlank: ~
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\NotBlank()
     */
    public $name;}

Protected和private屬性以及“getter”方法也可以被驗證(見 約束的投放范圍)。

使用驗證服務(wù) ?

接下來,要真正的校驗 Author 對象,使用 validator 服務(wù)(Validator 類)的 validate 方法。 validator 的工作很簡單:讀取一個類的約束規(guī)則來校驗對象數(shù)據(jù)是否滿足這些約束。如果驗證失敗,一個非空的錯誤列表(ConstraintViolationList類)將被返回。在控制器中實踐這個簡單例子:

// ...use Symfony\Component\HttpFoundation\Response;use AppBundle\Entity\Author; // ...public function authorAction(){
    $author = new Author();     // ... do something to the $author object
    // ... 對 $author 對象做一些事     $validator = $this->get('validator');
    $errors = $validator->validate($author);     if (count($errors) > 0) {
        /*
         * Uses a __toString method on the $errors variable which is a
         * ConstraintViolationList object. This gives us a nice string
         * for debugging.
         * 對 $errors 變量,即 ConstraintViolationList 對象,使用 __toString 方法。
         * 這給了我們一個美觀的字符串用于調(diào)試。
         */
        $errorsString = (string) $errors;         return new Response($errorsString);
    }     return new Response('The author is valid! Yes!');}

如果 $name 屬性是空的,你會看到一個錯誤信息:

1
2
AppBundle\Author.name:
  This value should not be blank

如果你為 name 屬性插入一個值,令人高興的成功信息就會出現(xiàn)。

多數(shù)時候,你不需要直接跟 validator 服務(wù)互動,或者毋須為輸出錯誤信息擔(dān)心。多數(shù)情況下,你在處理提交過來的表單數(shù)據(jù)時,間接地使用validation驗證。參考 驗證與表單 以了解更多。

你也可以傳遞“錯誤信息集合”(collection of errors)到模版中:

if (count($errors) > 0) {
    return $this->render('author/validation.html.twig', array(
        'errors' => $errors,
    ));}

在模版中,你可以根據(jù)需要精確輸出錯誤列表:

PHP:<!-- app/Resources/views/author/validation.html.php -->
<h3>The author has the following errors</h3>
<ul><?php foreach ($errors as $error): ?>
    <li><?php echo $error->getMessage() ?></li><?php endforeach ?></ul>
Twig:{# app/Resources/views/author/validation.html.twig #}<h3>The author has the following errors</h3>
<ul>{% for error in errors %}
    <li>{{ error.message }}</li>{% endfor %}</ul>


每一個驗證錯誤(被稱為“constraint violation/約束違反”)都由一個 ConstraintViolation 對象來呈現(xiàn)。

配置 ?

Symfony的validator是默認(rèn)開啟的,但是如果你使用annotation方式來指定約束,必須顯式地開啟(用于驗證的)annotation:

PHP:// app/config/config.php$container->loadFromExtension('framework', array(
    'validation' => array(
        'enable_annotations' => true,
    ),));
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:framework="http://symfony.com/schema/dic/symfony"    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd        http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">     <framework:config>
       <framework:validation enable-annotations="true" />    </framework:config></container>
YAML:# app/config/config.ymlframework:
    validation: { enable_annotations: true }


約束規(guī)則 ?

Validator 被設(shè)計成針對 約束(即規(guī)則)來驗證對象。要驗證一個對象,只需把一或多個約束映射到它要驗證的類,然后再把它傳遞給 validator 服務(wù)即可。

在幕后,一個約束就是一個PHP對象,它可以生成一個用于決斷的聲明。在實踐中,一個約束可以是“蛋糕不能燒”。在Symfony中,約束是類似的:它們就是“條件是否為真”的斷言。給定一個值,約束會告訴你這個值是否遵守了你的約束規(guī)則。

支持的約束 ?

Symfony封裝了很多最常用的約束:

基本約束 ?

這些是基本的約束:使用它們來斷言屬性值相關(guān)的非?;A(chǔ)的東西,或者斷言你程序中的方法之返回值。

字符串約束 ?

數(shù)字約束 ?

比較約束 ?

日期約束 ?

Collection約束 ?

文件約束 ?

財務(wù)數(shù)字約束 ?

其他約束 ?

你也可以創(chuàng)建自己的自定義約束。如何創(chuàng)建自定義的驗證約束 一文覆蓋了此話題。

約束的配置 ?

一些約束,像是 NotBlank 較為簡單,而其他一些像是  Choice 約束,有許多可用的配置選項。假設(shè) Author 類有另外一個屬性叫 gender,該屬性可以被設(shè)置為“male”、“female” 或 “other”:

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
    public $gender;     // ...     public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        // ...         $metadata->addPropertyConstraint('gender', new Assert\Choice(array(
            'choices' => array('male', 'female', 'other'),
            'message' => 'Choose a valid gender.',
        )));
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <property name="gender">
            <constraint name="Choice">
                <option name="choices">
                    <value>male</value>
                    <value>female</value>
                    <value>other</value>
                </option>
                <option name="message">Choose a valid gender.</option>
            </constraint>
        </property>         <!-- ... -->
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    properties:
        gender:
            - Choice: { choices: [male, female, other], message: Choose a valid gender. }
        # ...
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\Choice(
     *     choices = { "male", "female", "other" },
     *     message = "Choose a valid gender."
     * )
     */
    public $gender;     // ...}

約束的選項始終可以通過一個數(shù)組來傳遞的。有些約束也允許你傳入一個 ”default” 選項的值來代替這個數(shù)組。在 Choice 約束中,choices 選項就可以通過這種方式指定。

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
    protected $gender;     public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        // ...         $metadata->addPropertyConstraint(
            'gender',
            new Assert\Choice(array('male', 'female', 'other'))
        );
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <property name="gender">
            <constraint name="Choice">
                <value>male</value>
                <value>female</value>
                <value>other</value>
            </constraint>
        </property>         <!-- ... -->
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    properties:
        gender:
            - Choice: [male, female, other]
        # ...
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\Choice({"male", "female", "other"})
     */
    protected $gender;     // ...}

這純粹是為了讓最常見的配置選項在用起來時更加的簡單快速。

如果你不確定如何指定一個選項,要么去查看API文檔,要么為了保險起見,通過一個選項數(shù)組來傳入(即上面第一種方式)。

約束的目標(biāo) ?

約束可以被應(yīng)用到類的屬性(如 name)或者一個公共的getter方法(如 getFullName)乃至整個類上。屬性約束最常用也最簡單,而Getter約束則允許你指定更加復(fù)雜的驗證規(guī)則。最后,如果,類約束的使用場景是,你要將類作為整體進(jìn)行驗證。

屬性約束 ?

類屬性的驗證是一個最基本的驗證技巧。Symfony允許你校驗 private, protected 或者 public 屬性。下面代碼展示了如何配置 Author 對象的 $firstName 屬性,令其至少有3個字符:

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
    private $firstName;     public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('firstName', new Assert\NotBlank());
        $metadata->addPropertyConstraint(
            'firstName',
            new Assert\Length(array("min" => 3))
        );
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <property name="firstName">
            <constraint name="NotBlank" />
            <constraint name="Length">
                <option name="min">3</option>
            </constraint>
        </property>
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    properties:
        firstName:
            - NotBlank: ~
            - Length:
                min: 3
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\NotBlank()
     * @Assert\Length(min=3)
     */
    private $firstName;}

Getters約束 ?

約束也可以應(yīng)用于方法的返回值。Symfony允許你把一個約束添加到任何“get”、“is” 或者 “has”開頭的public方法。這一類方法被稱為“getters”。

這種技巧的好處是允許你動態(tài)驗證你的對象。例如,假設(shè)你想確保密碼字段不能匹配到用戶的firstname(出于安全原因)。你可以通過創(chuàng)建一個 isPasswordLegal 方法,然后斷言該方法必須返回 true 來實現(xiàn):

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addGetterConstraint('passwordLegal', new Assert\IsTrue(array(
            'message' => 'The password cannot match your first name',
        )));
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <getter property="passwordLegal">
            <constraint name="IsTrue">
                <option name="message">The password cannot match your first name</option>
            </constraint>
        </getter>
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    getters:
        passwordLegal:
            - 'IsTrue': { message: 'The password cannot match your first name' }
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\IsTrue(message = "The password cannot match your first name")
     */
    public function isPasswordLegal()
    {
        // ... return true or false
    }}

現(xiàn)在,創(chuàng)建一個 isPasswordLegal() 方法,含有你所需的邏輯:

public function isPasswordLegal(){
    return $this->firstName !== $this->password;}


眼尖的人可能會注意到,在YAML, XML和PHP的約束配置格式中,getter的前綴(“get”、”is” 或者 “has”) 在映射時被忽略了。這能讓你在不改變驗證邏輯的前提下,把一個約束移動到后面的一個同名屬性之上(反之亦然)。


類約束 ?

有一些約束可以應(yīng)用到被驗證的整個類。例如,Callback 類型的約束,就是一個可以作用到類本身的通用約束。當(dāng)類被驗證時,約束所指定的方法將被直接執(zhí)行,以便提供更多的自定義驗證。

總結(jié) ?

Symfony的 validator(驗證)是一個強(qiáng)大的工具,它可以被用來保證任何對象之?dāng)?shù)據(jù)的合法性。它的強(qiáng)大來源自約束規(guī)則(constraints),你可以把它應(yīng)用到對象的屬性和getter方法上。雖然,多數(shù)情況下都是在使用表單時間接應(yīng)用了驗證框架,記得,它可以用在任何地方去驗證任何對象。