ホームページ >バックエンド開発 >PHPチュートリアル >symfony データ検証手法の分析

symfony データ検証手法の分析

不言
不言オリジナル
2018-03-29 16:53:011450ブラウズ

この記事では、Symfony データ検証方法を例とともに分析します。興味のある方は参照してください。検証は Web アプリケーションの一般的なタスクです。フォームに入力されたデータは検証される必要があります。データは、データベースに書き込まれる前、または Web サービスに渡されるときにも検証する必要があります。

Symfony2 には Validator コンポーネントが搭載されており、検証作業をシンプルかつ理解しやすくしています。このコンポーネントは、JSR303 Bean 検証仕様に基づいています。 PHP で使用するための Java 仕様。

基本的な検証

検証を理解する最良の方法は、検証がどのように実行されるかを確認することです。まず、アプリケーションのどこかで使用される PHP オブジェクトを作成したと仮定します。

コードは次のとおりです:

//src/Acme/BlogBundle/Entity/Author.php
namespace Acme\BlogBundle\Entity;
class Author
{
public $name;
}


ここまでは、アプリケーションの何らかの目的を果たす単なる通常のクラスです。検証の目的は、オブジェクトのデータが合法かどうかを判断することです。この目的のために、ルールまたは制約のリストに従ってオブジェクトを構成し、そのデータを合法にする必要があります。これらのルールは、さまざまな形式 (YAML、XML、クラス宣言、PHP など) で記述できます。たとえば、属性 $name を空にすることはできないので、次のルールを追加します。

YAML 形式:

コードは次のとおりです:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
name:
- NotBlank: ~


クラス宣言の形式:

コードは次のとおりです:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\NotBlank()
*/
public $name;
}

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">

PHPコード形式:

コードは次のとおりです:

// src/Acme/BlogBundle/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(&#39;name&#39;, new NotBlank());
}
}

保護されたプライベート属性とゲッターメソッドも検証できます。

バリデーターサービスを使用します:

次に、バリデーターサービスの validate メソッドを使用して、Author オブジェクトを実際に検証します。バリデーターの仕事は単純です。クラスの制約ルールを読み取り、オブジェクトのデータがこれらのルール制約に準拠しているかどうかを検証します。検証が失敗した場合は、エラー配列が返されます。次に、コントローラーで実行します:

コードは次のとおりです:

use Symfony\Component\HttpFoundation\Response;
use Acme\BlogBundle\Entity\Author;
//...
public function indexAction()
{
$author = new Author();
//... 对$auother对象做些什么

$validator = $this->get(&#39;validator&#39;);
$errors = $validator->validate($author);
if(count($errors) >0){
return new Response(print_r($errors, true));
}else{
return new Response(&#39;The author is valid! Yes!&#39;);
}
}


$name 属性が空の場合、次のエラー メッセージが表示されます:

AcmeBlogBu​​ndleAuthor.name:
この値は使用できません空白にしてください

$name 属性の値を挿入すると、成功を示すメッセージが表示されます。

ほとんどの場合、バリデーターサービスと直接通信する必要はなく、印刷エラーについて心配する必要もまったくありません。

ほとんどの場合、送信されたフォーム データを処理するときに間接的に検証を使用します。

一連のエラー メッセージをテンプレートに渡すこともできます:

コードは次のとおりです:

if(count($errors)>0){
return $this->render(&#39;AcmeBlogBundle:Author:validate.html.twig&#39;,array(
&#39;errors&#39; => $errors,
));
}else{
//...
}


テンプレートでは、必要に応じて正確にエラー リストを出力できます:

Twig 形式:

コードは次のとおりです:

{# src/Acme/BlogBundle/Resources/views/Author/validate.html.twig #}
The author has the following errros
{% for error in errors %}
{{ error.message }}
{% endfor %}

チェックサムフォーム

validatorサービスを使用すると、いつでも任意のオブジェクトを検証できます。 実際、フォームを処理するときに間接的にバリデーターを使用することがよくあります。 Symfony のフォーム ライブラリは、データが送信されてバインドされた後、間接的にバリデーター サービスを使用して、基礎となるオブジェクトを検証します。オブジェクト制約違反情報は FieldError オブジェクトに変換され、フォームに簡単に表示できます。コントローラーでの従来のフォーム送信プロセスは次のとおりです:


コードは次のとおりです:

use Acme\BlogBundle\Entity\Author;
use Acme\BlogBundle\Form\AuthorType;
use Acme\Component\HttpFoundation\Request;
//...
public function updateAction(Request $request)
{
$author = new Acme\BlogBundle\Entity\Author();
$form = $this->createForm(new AuthorType(),$author);
if($request->getMethod() ==&#39;POST&#39;){
$form->bindRequest($request);

if($form->isvalid()){
//对$author做一些操作
return $this->redirect($this->generateUrl(&#39;...&#39;));
}
}
return $this->render(&#39;BlogBundle:Author:form.html.twig&#39;,array(
&#39;form&#39; => $form->createView(),
));
}

設定:

Symfony2 のバリデーターはデフォルトで利用可能です。ただし、life メソッドを使用して制約を指定する場合は、宣言関数を明示的に有効にする必要があります:

YAML 形式:

コードは次のとおりです:

# app/config/config.yml
framework:
validation: {enable_annotations: true }

XML 形式:

コードは次のとおりです:



PHP コード形式:

コードは次のとおりです:

// app/config/config.php
$contianer->loadFromExtension(&#39;framework&#39;,array(&#39;validation&#39;=> array(
&#39;enable_annotations&#39;=>true,
)));

制約ルール

Validator は、制約ルールに従ってオブジェクトを検証するように設計されています。オブジェクトを検証するには、検証対象のクラスに 1 つ以上の制約をマップし、それを検証サービスに渡すだけです。

本質的に、制約は決定ステートメントを生成する単純な PHP オブジェクトです。 現実の世界では、制約は「ケーキを焼くことができない」などのルール制約になる可能性があります。 Symfony2 では、制約はすべて同じです。制約は特定の条件が true であるかどうかを決定します。値を指定すると、その値が制約ルールに従っているかどうかが制約によってわかります。

Symfony2 でサポートされている制約ルール

最初は基本的な制約ルールです。オブジェクトのプロパティの値やメソッドの戻り値など、非常に基本的なものを決定するために使用します。

NotBlank、Blank、NotNull、Null、True、False、Type

文字列制約: Email、MinLength、MaxLength、Url、Regex、Ip など

数値制約: Max、Min

日付制約: Date、DateTime、Time

コレクション制約: Choice、Collection、UniqueEntity、Language、Locale、 Country など。

ファイル制約:File、Image
その他の制約:Callback、All、Valid

独自のカスタム制約を作成することもできます。

制約の設定:

NotBlank などの一部の制約は非常に単純ですが、Choice 制約などのその他の制約には設定が必要な設定項目が多数あります。 Author クラスに別の属性があると仮定します。gener は「男性」または「女性」に設定できます。

YAML 形式:

コードは次のとおりです:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
gener:
- Choice: { choices: [male, female], message: Choos a valid gender. }


クラス宣言形式:

コードは次のとおりです。次のように:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\Choice(
* choices = {"male","female"},
* message = "Choose a valid gender."
* )
*/
public $gender;
}


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">

PHP コード形式:

コードは次のとおりです:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
class Author
{
public $gender;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;gender&#39;, new Choice(array(
&#39;choices&#39; => array(&#39;male&#39;, &#39;female&#39;),
&#39;message&#39; => &#39;Choose a valid gender.&#39;,
)));
}
}

一个约束的选项通常都是通过一个数组来传递的。有些约束也允许你传递一个值。"default"在数组中是可选的。在Choice约束时,choices选项就可以通过这种方式指定。

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
gender:
- Choice: [male, female]

类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\Choice({"male", "female"})
*/
protected $gender;
}

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">
male
female

PHP格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\Choice;
class Author
{
protected $gender;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;gender&#39;, new Choice(array(&#39;male&#39;, &#39;female&#39;)));
}
}


约束目标

约束可以被用于一个类的属性或者一个公共的getter方法。属性约束最常用也最简单,而公共的getter方法约束则允许你指定一个复杂的约束规则。

属性约束:

校验类的属性石一个最常规的校验技术。Symfony2允许你校验private,protected或者public属性。下面代码显示如何配置Author对象的$firstName属性至少有3个字符:

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
firstName:
- NotBlank: ~
- MinLength: 3


类声明格式:

代码如下:

// Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\NotBlank()
* @Assert\MinLength(3)
*/
private $firstName;
}


XML格式:

代码如下:





3


PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\MinLength;
class Author
{
private $firstName;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;firstName&#39;, new NotBlank());
$metadata->addPropertyConstraint(&#39;firstName&#39;, new MinLength(3));
}
}

Getters

约束也可以应用于一个方法的返回值。Symfony2 允许你添加一个约束到任何"get"或者 "is"开头的public方法。该技术的好处是允许你动态的校验你的对象。比如,假设你想确认密码字段不匹配用户的first name(因为安全原因)。你可以通过创建一个idPasswordLegal 方法,然后决断这个方法必须返回true:

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
getters:
passwordLegal:
- "True": { message: "The password cannot match your first name" }

类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\True(message = "The password cannot match your first name")
*/
public function isPasswordLegal()
{
// return true or false
}
}


XML格式:

代码如下:


PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\True;
class Author
{
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addGetterConstraint(&#39;passwordLegal&#39;, new True(array(
&#39;message&#39; => &#39;The password cannot match your first name&#39;,
)));
}
}

现在我们创建一个isPasswordLegal()方法,并且包含你需要逻辑:

代码如下:

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

眼尖的人可能会注意到getter的前缀("get"或者"is")在映射时被忽略了。这允许你在不改变校验规则的前提下,把一个约束移动到一个具有同名属性上,反之亦然。


类:

一些约束应用到整个类被校验上面。比如,Callback约束是一个通用约束,它可以应用到类自身。当类被校验时,被约束描述的方法只是被执行这样每一个可以提供更个性化的校验。

校验分组

到目前为止,你已经能够添加约束到类并询问是否该类传入所有定义的约束规则。一些情况下,你只需要使用该类的其中某些规则来校验一个对象。要做到这些,你可以组织每一个约束到一个或者多个校验组中,然后应用使用其中一组校验。比如,假设你有一个User类,它会在用户注册和用户更新他们的联系信息时使用。

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\User:
properties:
email:
- Email: { groups: [registration] }
password:
- NotBlank: { groups: [registration] }
- MinLength: { limit: 7, groups: [registration] }
city:
- MinLength: 2


类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/User.php
namespace Acme\BlogBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
class User implements UserInterface
{
/**
* @Assert\Email(groups={"registration"})
*/
private $email;
/**
* @Assert\NotBlank(groups={"registration"})
* @Assert\MinLength(limit=7, groups={"registration"})
*/
private $password;
/**
* @Assert\MinLength(2)
*/
private $city;
}

XML格式:

代码如下:

7

PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/User.php
namespace Acme\BlogBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\MinLength;
class User
{
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;email&#39;, new Email(array(
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;password&#39;, new NotBlank(array(
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;password&#39;, new MinLength(array(
&#39;limit&#39; => 7,
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;city&#39;, new MinLength(3));
}
}

这里我们配置了两个校验组:
default默认组: 包括所有没有分配到任何组的约束规则
registration: 只包含了email和password字段的校验规则

告诉validator使用指定的校验组,传一个或者多个组名作为validate()方法的第二个参数即可:

代码如下:

$errors = $validator->validate($author,array(&#39;registration&#39;));

值和数组校验

到目前为止,我们已经看了如何校验整个对象。但是有时候,我们可能想值校验一个单独的值,比如校验一个字符串是不是一个合法的email地址。这非常简单,在Controller类中进行如下:

代码如下:

// 在controller类前引用相应的校验命名空间
use Symfony\Component\Validator\Constraints\Email;
public function addEmailAction($email)
{
$emailConstraint = new Email();
// 所有的校验选项(options)都可以这样设置
$emailConstraint->message = &#39;Invalid email address&#39;;
// 使用validator来校验一个值
$errorList = $this->get(&#39;validator&#39;)->validateValue($email, $emailConstraint);
if (count($errorList) == 0) {
// 这是一个合法的email地址,可以做些什么
} else {
// 这是一个非法的email地址
$errorMessage = $errorList[0]->getMessage()
// 做一些错误处理
}
// ...
}


通过调用validator的validateValue方法,你可以传入一个原始值和一个你要使用的校验对象。该方法会返回一个ConstraintViolationList对象,它扮演的只是一个错误信息数组的角色。集合中的每一个错误是一个ConstraintViolation对象,使用对象的getMessage方法可以获取错误信息。

总结:

Symfony2 的validator是一个强大的工具,它可以被用来保证任何对象数据的合法性。它的强大来源于约束规则,你可以把它们应用于你对象的属性和getter方法。其实,你大多数情况下都是在使用表单时,间接的应用了校验框架,记住它可以被应用于任何地方校验任何对象。

相关推荐:

Symfony查询方法小结分享

Symfony2针对输入时间进行查询实例详解

详解Symfony2框架表单的用法

以上がsymfony データ検証手法の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。