怜蚌枈み、怜蚌枈み...、怜蚌枈み PHPでデヌタバリデヌタヌを比范する


Michiana Stransportation 自転車店 から撮圱した画像


それでもKontrolioが䜕であるかわからない堎合は、最初の郚分「 デヌタを管理する 」を読むこずをお勧めしたす。 芁するに、これはPHPで曞かれた私のデヌタ怜蚌ラむブラリです。

前の蚘事で、私は自分のラむブラリず他の利甚可胜な゜リュヌションずの比范を曞くこずを玄束したので、今日はAura.Filter 、 Respect Validation 、 Sirius Validation 、およびValitronを䜿甚した怜蚌に぀いお芋おいきたす。


開発䞭の特定の公共サヌビスがあるこずを想像しおみたしょう。これには、すべおの機胜ぞのフルアクセスのためのナヌザヌの登録が含たれたす。 したがっお、登録フォヌムには次のフィヌルドが含たれたす。


  1. 名前。 正確に2぀の単語を含める必芁がありたす。最初の単語はナヌザヌ名で、2番目の単語は姓です。
  2. ログむンしたす。 倀が枡される堎合、ラテン文字、ハむフン、アンダヌスコアのみが䜿甚されたす。
  3. メヌル 有効なメヌルアドレスを含める必芁がありたす。
  4. パスワヌド。 むンストヌルする必芁があり、長さは64文字以䞋である必芁がありたす。
  5. 同意した。 利甚芏玄ぞの同意を確認するためにナヌザヌが蚭定する必芁がある兞型的なフラグ。

したがっお、架空のサヌビスに登録するためにナヌザヌが入力する必芁がある5぀のフィヌルドがありたす。 完党に無効なデヌタを受け取ったず想像しおみたしょう。


$data = [ 'name' => '', //     'login' => '@lbert', // ""  @ 'email' => '-  ', //    e-mail 'password' => '' //     // 'agreed'   ,       ]; 

Aura.filter


Aura.Filterを䜿甚した怜蚌は、フィルタヌファクトリから始たりたす。 個々の倀ではなく配列を怜蚌するため、いわゆる「サブゞェクトフィルタヌ」を䜜成する必芁がありたす。


ルヌルを定矩する


 use Aura\Filter\FilterFactory; $filter = (new FilterFactory)->newSubjectFilter(); $filter->validate('name') ->isNotBlank() ->is('two_words') ->setMessage('     .'); $filter->validate('login') ->isBlankOr('alnum') ->setMessage('   ,      .'); $filter->validate('email') ->isNotBlank() ->is('email') ->setMessage(',    . .'); $filter->validate('password') ->isNotBlank() ->is('strlenMax', 64) ->setMessage(',  .'); $filter->validate('agreed') ->is('callback', function($subject, $field) { return $subject->{$field} === true; })->setMessage('     .'); 

ご芧のずおり、ルヌルの説明は非垞に簡単です。 Aura.Filterは、すぐに䜿える䟿利なルヌルのセット党䜓を提䟛し、それらのいく぀かは䞊の䟋で䜿甚されおいたす


  1. isNotBlankメ゜ッド。 フィヌルドをnullにできないこずを瀺したす。
  2. 幎 このルヌルでは、ラテン文字のみが蚱可されたす。
  3. メヌル そしお、それは明らかです:)
  4. strlenMax。 isメ゜ッドの2番目の匕数で指定された長さをフィヌルドが超えられないこずを瀺したす。
  5. コヌルバック。 このタむプのルヌルは、Kontrolioのクロヌゞャヌに䌌おいたす。 クロヌゞャヌの圢匏でルヌルを定矩できたす。 このクロヌゞャでは、Aura.Filterが「件名」、フォヌムからのデヌタの配列、およびこの堎合agreedしたフィヌルドを枡したす。

きっずあなたは、私がtwo_wordsルヌルを指定しなかったこずに気づいたでしょう。 圓然、Aura.Filterにはそのようなルヌルはないため、䜜成する必芁がありたす。 ドキュメンテヌションが蚀うように、これはルヌルのために別のクラスを䜿甚しお行われたす


 /** * ,    . *      :   ,   . */ class UserNameRule { /** *   . * * @param object|array $subject * @param string $field * @param int $max * * @return bool */ public function __invoke($subject, $field, $max = null) { $value = $subject->{$field}; if ( ! is_scalar($value)) { return false; } return (bool) preg_match('/^[A-Za-z]+\s[A-Za-z]+$/u', $value); } } 

2番目のステップは、フィルタヌファクトリヌに新しいルヌルを知らせるこずです。 これは、最初の匕数をルヌルの配列ずしおフィルタヌファクトリに枡すこずで実行されたす。


次のステップは、新しいルヌルを䜜成し、それを䜿甚するこずをAura.Filterに通知するこずです。 これは、ルヌルの配列をファクトリヌの最初の匕数に枡すこずで実行されたす。


 use Aura\Filter\FilterFactory; $rules = [ 'two_words' => function() { return new UserNameRule; } ]; $filter = (new FilterFactory($rules))->newSubjectFilter(); 

これで、 two_wordsルヌルは、暙準パッケヌゞの他のルヌルず同じ方法で䜿甚できたす。


フィヌドバック


芚えおいるように、各フィヌルドに間違った倀が含たれおいるか、たったく含たれおいないため、怜蚌する入力デヌタは完党に無効です。 したがっお、怜蚌の結果ずしお、゚ラヌおよび゚ラヌに関する察応するメッセヌゞを受け取るず想定されたす。


次のようにAura.Filterで怜蚌したす。


 $valid = $filter->apply($data); if ( ! $valid) { $failures = $filter->getFailures(); $messages = $failures->getMessages(); } 

配列は$ messagesに曞き蟌たれるため、メッセヌゞを衚瀺するには、ネストされた2぀のforeachが必芁です。


 <ul class="errors"> <?php foreach ($messages as $field => $errors) { foreach ($errors as $error) { printf('<li class="error">%s</li>', $error); } } ?> </ul> 

怜蚌の尊重


比范で䜿甚した2番目のラむブラリは、 Respect Validationず呌ばれる比范的䞀般的な゜リュヌションです。 人々は圌女を信頌しおいるので、芋るべきものがあるず思いたす。


実隓の玔床のために、ラむブラリを比范するずき、最初に定矩された同じデヌタセットを䜿甚したす。


 use Respect\Validation\Validator as v; $data = [ 'name' => '', //     'login' => '@lbert', // ""  @ 'email' => '-  ', //    e-mail 'password' => '' //     // 'agreed'   ,       ]; 

ルヌルを定矩する


Aura.Filterず同様に、ナヌザヌ名に独自の怜蚌ルヌルが必芁なので、始めたしょう


 namespace MyNamespace; use Respect\Validation\Rules\AbstractRule; class UserNameRule extends AbstractRule { public function validate($input) { return (bool) preg_match('/^[A-Za-z]+\s[A-Za-z]+$/u', $input); } } 

倖郚ルヌルAPIはAura.Filterずほが同じです。__invokeマゞックの代わりにvalidateメ゜ッドのみが䜿甚されたす。 私にずっお、このAPIはよりシンプルで理解しやすいように芋えたした。 たあ、それはKontrolioに近いです:)


ドキュメントにはこれに関する蚀及はありたせんでしたが、ルヌル自䜓に加えお、独自のタむプの䟋倖を䜜成する必芁がありたす。 䟋倖クラスの名前は、ルヌルのクラス名ず䟋倖の接尟蟞で構成する必芁がありたす。


 use Respect\Validation\Exceptions\NestedValidationException; class UserNameRuleException extends NestedValidationException { // } 

さお、最埌に、デヌタを怜蚌できたす。 最初に、バリデヌタヌに新しいルヌルを枡しお、圌がそれに぀いお孊習し、将来䜿甚できるようにしたす。 Respect Validationでは、 withメ゜ッドを呌び出しお、非暙準のルヌルを含むネヌムスペヌスを枡すこずでこれを行いたす。


 v::with('MyNamespace\\'); 

これで、 MyNamespace名前空間にあるすべおの非暙準ルヌルがバリデヌタヌによっお「認識」されたす。 次のステップは、必芁なルヌルを蚘述し、怜蚌を実行するこずです。


 v::attribute('name', v::userNameRule()) ->attribute('login', v::alnum('-_')) ->attribute('email', v::email()) ->attribute('password', v::notEmpty()->stringType()->length(null, 64)) ->attribute('agreed', v::trueVal()) ->assert((object) $data); 

name属性にルヌルを適甚する方法に泚目しおください。 ここでは、クラスルヌルの名前がバリデヌタメ゜ッドの名前に倉換されたした。 䞀般に、残りのルヌルは盎感的です。


それずは別に、 $デヌタ配列をオブゞェクトにキャストする理由に蚀及する䟡倀がありたす。 事実は、Respect Validationは配列ではなく入力ずしおオブゞェクトを受け入れるずいうこずです。 このラむブラリを䜿甚しお開発する堎合は、これを考慮する必芁がありたす。


フィヌドバック


Aura.Filterずは異なり、Respectバリデヌタヌは怜蚌が倱敗するず䟋倖をスロヌしたす。 たた、この䟋倖には怜蚌゚ラヌメッセヌゞが含たれおいたす。 したがっお、今瀺した䟋は次のように蚘述する必芁がありたす。


 try { v::with('RespectValidationExample\\'); v::attribute('name', v::userNameRule()) ->attribute('login', v::alnum('-_')) ->attribute('email', v::email()) ->attribute('password', v::notEmpty()->stringType()->length(null, 64)) ->attribute('agreed', v::trueVal()) ->assert((object) $data); } catch (NestedValidationException $ex) { $messages = $ex->getMessages(); } 

getMessagesを䜿甚しお、怜蚌プロセス䞭にバリデヌタヌが収集したすべおのメッセヌゞのフラット配列を取埗したす。 配列をダンプするず、次のような結果が埗られたす。


 array(5) { [0] => string(29) “Data validation failed for %s” [1] => string(60) “login must contain only letters (az), digits (0–9) and “-_”” [2] => string(25) “email must be valid email” [3] => string(26) “password must not be empty” [4] => string(32) “Attribute agreed must be present” } 

メッセヌゞは自分で亀換できたす。 おそらく私はこのラむブラリを䜕らかの圢で誀解しおいるかもしれたせんが、このプロセスは私にはそれほど明癜ではないようです。凊理された䟋倖でfindMessagesメ゜ッドを䜿甚する必芁がありたす。


 $ex->findMessages([ 'userNameRule' => '      .', 'alnum' => '    .', 'email' => '       e-mail.', 'notEmpty' => '     ?', 'agreed' => ',    .' ]); 

間違いが䜕なのかはわかりたせんが、理解できなかったこずがいく぀かありたす。 䞊蚘の方法でルヌルを定矩するず、次のようになりたす。


 array(5) { [0] => string(40) “      .” [1] => string(31) “    .” [2] => string(25) “email must be valid email” [3] => string(5) “     ?” [4] => string(9) “,    .” } 

ご芧のずおり、電子メヌルフィヌルドのメッセヌゞは適甚されず、暙準のたたです。 しかし、むンデックス4の背埌にあるメッセヌゞは逆です これは、ルヌルの名前ではなく、フィヌルドの名前を䜿甚したにもかかわらずです。 䞀方、ルヌルの名前trueValを䜿甚した堎合、メッセヌゞはどこかで倱われたす。 このラむブラリの経隓豊富なナヌザヌによるコメントは倧歓迎です。


シリりス怜蚌


では、次のラむブラリに移り、同様のタスクをどのように凊理するかを芋おみたしょう。


ルヌルを定矩する


繰り返したすが、ナヌザヌ名のルヌルを定矩する必芁がありたす。 次のように蚘述したす。


 class UserNameRule extends AbstractRule { //    const MESSAGE = '      .'; const LABELED_MESSAGE = '{label}     .'; public function validate($value, $valueIdentifier = null) { return (bool) preg_match('/^[A-Za-z]+\s[A-Za-z]+$/u', $value); } } 

すでに怜蚎されおいるラむブラリず比范したアプロヌチの違いに泚意しおください。 プロパティ、メ゜ッド、たたはルヌル匕数を䜿甚するのではなく、定数で2皮類のメッセヌゞを定矩したす。


次に、怜蚌ロゞックに぀いお説明したす。


 $validator = new Validator; $validator ->add('name', 'required | MyApp\Validation\Rule\UserNameRule') ->add('login', 'required | alphanumhyphen', null, '     ,   .') ->add('email', 'required | email', null, ',   e-mail.') ->add('password', 'required | maxlength(64)', null, ' , .') ->add('agree', 'required | equal(true)', null, '    ?'); 

ご芧のずおり、ルヌルのセットは非垞にシンプルで読みやすいです。 説明のために、氎平ダッシュで区切られた名前を䜿甚したす。 このアプロヌチは、LaravelずKontrolioで䜿甚されおいるアプロヌチに䌌おいたす。


addメ゜ッドの4番目の匕数は、怜蚌が倱敗した堎合にSiriusが䜿甚する怜蚌゚ラヌメッセヌゞを瀺したす。 新しいUserNameRuleルヌルにメッセヌゞを远加しなかったのはなぜですか


 $validator->add('name', 'required | MyApp\Validation\Rule\UserNameRule') 

これは、メッセヌゞがクラス定数で既に蚘述されおいるためです。


 class UserNameRule extends AbstractRule { //    const MESSAGE = '      .'; ... 

別のオプションは、バリデヌタヌ自䜓のaddMessageメ゜ッドを䜿甚するこずです。


 $validator->addMessage('email', ',   e-mail.'); 

カスタムルヌルはクラスのフルネヌムで識別されたすが、Kontrolioでぱむリアス/゚むリアスを蚭定できたす。


フィヌドバック


怜蚌を実行するには、バリデヌタヌのvalidateメ゜ッドを呌び出し、デヌタを枡したす


 $data = [ 'name' => '', //     'login' => '@lbert', // ""  @ 'email' => '-  ', //    e-mail 'password' => '' //     // 'agreed'   ,       ]; $validator->validate($data); 

Respectずは異なり、Siriusは䟋倖をスロヌせず、単にfalseを返したす 。 怜蚌゚ラヌメッセヌゞは、 getMessagesバリデヌタメ゜ッドを介しお取埗できたす。 属性ごずにグルヌプ化された゚ラヌを返すため、゚ラヌを通過するには2぀のforeachルヌプが必芁です。


 foreach ($validator->getMessages() as $attribute => $messages) { foreach ($messages as $message) { echo $message->getTemplate() . "\n"; } } 

ここで、$ messageはSirius \ Validation \ ErrorMessageクラスのオブゞェクトであり、必芁なメッセヌゞを返すgetTemplateメ゜ッドがありたす。


バリトロン


さらに進みたしょう。 別の興味深い゜リュヌションは、 Valitronです。 バリトロンは、怜蚌ルヌルの远加ず蚘述の実装においお他ず異なりたす。


ルヌルを定矩する


最初の違い新しいルヌルを远加するには、別のクラスを䜜成する必芁はありたせん。 ブヌル倀の結果を返すクロヌゞャを䜿甚するだけです。


カスタムルヌルを远加するために、Valitronには静的なaddRuleメ゜ッドがありたす。このメ゜ッドでは、最初の2぀の匕数が必須で、3番目の匕数はオプションです。 ここでは、ルヌルの識別子、ロゞック、゚ラヌメッセヌゞがすぐに1か所に衚瀺されるため、この方法が気に入りたした。


 use Valitron\Validator; Validator::addRule('two_words', function($field, $value) { return (bool) preg_match('/^[A-Za-z]+\s[A-Za-z]+$/u', $value); }, '       .'); 

2番目の違いは、ルヌルが属性に適甚される方法です。 これたでのすべおのケヌスで、属性が本来のものであるこずがわかりたした。


Valitronは逆の方法で、最初に怜蚌ルヌルを蚭定したした。 ルヌルを蚘述するずき、これらのルヌルに属性を適甚したす。逆の堎合も同様です。


 $validator = new Validator($data); $validator ->rule('two_words', 'name')->label('') ->rule('required', [ 'name', 'login', 'email', 'password', 'agreed' ]) ->rule('slug', 'login') ->rule('email', 'email') ->rule('accepted', 'agreed'); 

䟋からわかるように、 ruleメ゜ッドでは、最初にルヌルの名前を蚘述し、次にこのルヌルに察応する必芁のある属性を指定したす。 より明癜な䟋は、このルヌルに属性がどのように「属する」かを瀺すrequiredルヌルです。


Valitronおよび私たちが怜蚎したその他の゜リュヌションは、暙準゚ラヌメッセヌゞを提䟛したす。 それらを単玔に䜿甚するず、各メッセヌゞが察応する属性の名前で始たるこずがわかりたす。


暙準以倖の゚ラヌメッセヌゞが䜿甚されおいる堎合でも、Valitronはメッセヌゞ本文の属性名を眮き換えたす。 そのため、空の文字列でlabelメ゜ッドを䜿甚しお属性名を削陀したした。


 $validator->rule('two_words', 'name')->label('') 

フィヌドバック


具䜓的には、怜蚌に関しおは、ValitronラむブラリAPIは、この蚘事で既に芋たものずほずんど倉わりたせん。 怜蚌を実行するには、 validateバリデヌタメ゜ッドを呌び出したす。


 $validator->validate(); 

怜蚌゚ラヌメッセヌゞは、 getErrorsメ゜ッドを䜿甚しお取埗できたす。


 $validator->errors(); 

ここでのメッセヌゞは、Sirius Validationず同じ方法で属性によっおグルヌプ化されたすが、メッセヌゞ甚の個別のクラスはなく、通垞の倚次元配列を取埗したす。


 foreach ($validator->errors() as $attribute => $messages) { foreach ($messages as $message) { echo $message . "\n"; } } 

コントロリオ


そしお最埌に、今日の最埌のラむブラリはKontrolioず呌ばれる私自身の開発です 。


ルヌルを定矩する


繰り返しになりたすが、5回目は、ナヌザヌ名の怜蚌ルヌルを䜜成したす。 すべおが比范的シンプルで暙準的です


 namespace MyProject\Validation\Rules; use Kontrolio\Rules\AbstractRule; class TwoWords extends Kontrolio\Rules\AbstractRule { public function isValid($input = null) { return (bool) preg_match('/^[A-Za-z]+\s[A-Za-z]+$/u', $input); } } 

次に、ファクトリを䜜成し、 extendメ゜ッドを䜿甚しおその䞭にルヌルを登録したす。


 namespace MyProject; use Kontrolio\Factory; use MyProject\Validation\Rules\TwoWords; $factory = Kontrolio\Factory::getInstance()->extend([TwoWords::class]); 

ルヌルを登録した埌、名前でtwo_wordsを含めお䜿甚できたす。 バリデヌタヌを䜜成したしょう


 $data = [ 'name' => '', //     'login' => '@lbert', // ""  @ 'email' => '-  ', //    e-mail 'password' => '' //     // 'agreed'   ,       ]; $rules = [ 'name' => 'two_words', 'login' => 'sometimes|alphadash', 'email' => 'email', 'password' => 'length:1,64', 'agreed' => 'accepted' ]; $messages = [ 'name' => '      .', 'login' => '    .', 'email' => '       e-mail.', 'password' => '     ?', 'agreed' => ',    .' ]; $validator = $factory->make($data, $rules, $messages); 

より詳现なバヌゞョンを䜿甚するこずもできたすが、Laravelで䜿甚される構文ず同様の構文を䜿甚しおルヌルを説明したした。


 $rules = [ 'name' => new TwoWords, 'login' => [new Sometimes, new Alphadash], 'email' => new Email, 'password' => new Length(1, 64), 'agreed' => new Accepted ]; 

フィヌドバック


怜蚌は、同じvalidateメ゜ッドで開始されたす。


 $validator->validate(); 

getErrorsたたはgetErrorsListメ゜ッドのいずれかを䜿甚しお゚ラヌメッセヌゞを取埗できるようになりたした。 最初のメ゜ッドはより耇雑な゚ラヌ出力を可胜にし、2番目のメ゜ッドはフラット配列を返したす。 getErrorsを䜿甚しお、次のようなメッセヌゞを衚瀺できたす。


 <ul class="errors"> <?php foreach ($errors as $attribute => $messages): ?> <li class="errors__attribute"> <b><?= $attribute; ?></b> <ul> <?php foreach ($messages as $message): ?> <li><?= $message; ?></li> <?php endforeach; ?> </ul> </li> <?php endforeach; ?> </ul> 

たた、 getErrorsListを䜿甚するず、メッセヌゞのより単玔なリストを䜜成できたす。


 <?php $errors = $validator->getErrorsList(); ?> <ul class="errors"> <?php foreach($errors as $error): ?> <li class="errors__error"><?= $error; ?></li> <?php endforeach; ?> </ul> 

たずめ


この蚘事では、次のラむブラリヌの䜿甚䟋を瀺したした。


  1. Aura.filter
  2. 怜蚌の尊重
  3. シリりス怜蚌
  4. バリトロン
  5. コントロリオ

「実䞖界の䟋」は単玔すぎるように思えるかもしれたせん。 確かに、ラむブラリの機胜の䞀郚は蚘事に含たれおいないため、同意する必芁がありたす。 原則ずしお、それがあなたにずっお興味深い堎合は、自分でその機胜を調べるこずができたす。


各ラむブラリは独自のチップを提䟛し、その暗い偎面を持っおいるので、奜みずタスクの問題だず思う-それを遞択するこず。


読んでくれおありがずう。 正しい遞択をしおください。



Source: https://habr.com/ru/post/J308298/


All Articles