「Runn Me!」次のPHP *フレームワークが教えてくれます。 そして、「Throw Me!」と聞きます。 パート2

*一般的に言って、これはまだフレームワークではありませんが、単なるライブラリのセットであり、少し後にフレームワークになります


私たちの物語の最初の部分の「クレイジーな成功」(もちろんここでは意見が少し異なります)から1週間も経っていません。2番目の部分をリリースするときです。

今日、私たちは未来のRunn Meのrunn /コアライブラリの底なしの深さへの旅を続けます! カットの下で、我々は深followingの以下の住民に会います:





前のシリーズ:


  1. 歴史的背景。 ObjectAsArray コレクション。 TypedCollection。 標準クラス

マルチ例外


最初はThrowableインターフェースでした。

トリッキーなこと。 標準のPHPライブラリの多くのインターフェイスのように、直接実装することは不可能ですが、このインターフェイスを実装するオブジェクトには、特別な超能力が与えられます。 ただし、「any」という言葉は明白な誇張です。利用できるのは、ライブラリ\ Exceptionから独自のクラスを継承することだけです。

Runn Me!で例外を使用して作業を行うのは、この継承です。

namespace Runn\Core; class Exception extends \Exception implements \JsonSerializable { public function jsonSerialize() { return ['code' => $this->getCode(), 'message' => $this->getMessage()]; } } 

JsonSerializableインターフェースの実装は、Runn \ Core \ Exceptionの理由ですぐに追加されました。これは、明日の未来のための明確なスタートです。ミドルウェアで例外をキャッチし、JSONにパックしてクライアントに返す方法を学びます。

ただし、「Runn Me!」は、リストを読み直すときに見えるほど退屈ではありません。 Runn \ Core名前空間のExceptionクラスに非常に近いもう1つの、ほとんど目に見えないRunn \ Core \ Exceptionsクラスです。 これは何?

これは複数の例外です。


そのような構造を使用する方法の簡単な例を見てみましょう。

 $exceptions = new Exceptions; $exceptions->add(new Exception('First')); $exceptions->add(new Exception('Second')); assert(2 === count($exceptions)); assert('First' === $exceptions[0]->getMessage()); assert('Second' === $exceptions[1]->getMessage()); if (!$exceptions->empty()) { throw $exceptions; } 

マルチ例外はどこに適用されますか?


おそらく、このパターンの最も「鮮やかな」アプリケーションは、標準のRunn Me!オブジェクトで提供される検証メカニズムです。

ライブラリの作成者は、検証エラーが例外である可能性があるというヒントでさえ、多くのプログラマの背中よりも低い書き込みを引き起こす可能性があることをよく知っています。 ただし、このアプローチから得られる可能性のある利益は、そこから予想されるマイナスよりも何倍も高いと判断しました。 したがって、無駄に燃やさないでください-例外と複数の例外によって検証エラーが実装されています。 この決定はなされており、控訴の対象ではありません。

ステップごとに、それがどのように機能するかを詳細に検討しましょう。

検証接続方法


標準オブジェクト(または、むしろHasInnerValidationInterfaceの子孫)内で、StdGetSetWValidateSanitizeTraitで説明されている参照実装からあまり逸脱していない場合は、検証接続メソッドを定義できます。

このようなメソッドの名前は、「検証」という単語で始まり、その後にキーの名前、検証する値、最初の大文字が続く必要があります。 例:

 class ValidationExampleClass extends Std { protected function validateFoo($val) { return true; } protected function validateBar($val) { return true; } } $obj = new ValidationExampleClass; $obj->foo = 42; $obj->bar = 'baz'; 

このコードは、validate validateFoo()とvalidateBar()を接続するための2つのメソッドを作成したことを示しています。 それらの最初は、プロパティ$ obj-> fooに値を割り当てる前に自動的に呼び出され、2番目は、$ obj-> bazの実際の変更の前にそれぞれ呼び出されます。

検証接続方法には、5つの可能な「動作」があります。

  1. メソッドはfalseを返します
  2. メソッドは単一の例外をスローします
  3. メソッドは複数の例外をスローします
  4. メソッドは例外ジェネレーターです
  5. そして最後に、メソッドは偽ではない何かを返しました

最も簡単なのはオプション1と5です。

最初のケースでは、何も起こりません。割り当ては「サイレント」にキャンセルされ、プロパティは新しい値を受け取りません。

5番目のケースでは、副作用を引き起こすことなく、プロパティに新しい値を「サイレントに」割り当てることも行われます。

少し複雑なオプション番号2、3、4。それらはすべて割り当ての廃止につながります。 しかし、それらが何を意図しているかを正確に理解するために、さらに先に進みます。

一括割り当て方法


StdGetSetWValidateSanitizeTraitトレイの検証接続メソッドの可能性を最大限に活用するために、重要なmerge()メソッドが再定義されました(これはStdクラスのコンストラクターでも使用されます)。

彼の作品を示すには、次の方法が最適です。

 class ValidationExampleClass extends Std { //   2:   protected function validateFoo($val) { if (empty($val)) { throw new Exception('foo is empty'); } } //   3:  protected function validateBar($val) { $errors = new ValidationErrors; //  , ,   Exceptions if (strlen($val) < 6) { $errors[] = new Exception('bar is too short'); } if (preg_match('~\d~', $val)) { $errors[] = new Exception('bar contains digits'); } if (!$errors->empty()) { throw $errors; } } //   4:   protected function validateBaz($val) { if (strlen($val) > 6) { yield new Exception('baz is too long'); } if (preg_match('~[az]~', $val)) { yield new Exception('baz contains letters'); } } } 

すべての可能な方法ですべての可能な検証ルールを特定したので、これらのすべてのルールに意図的に違反するオブジェクトを作成してみましょう。

 try { $obj = new ValidationExampleClass([ 'foo' => '', //   "" 'bar' => '123', //   - " "  " ", 'baz' => 'abcdefgh', //   - " "  " ", ]); } catch (Exceptions $errors) { foreach ($errors as $error) { // !      ! echo $error->getMessage(); } } 

どうしたの?

まず、merge()メソッドは、将来の検証エラーに備えて、Exceptionsクラスの空のコレクションを準備します。 次に、各キーについて、有効な場合、検証の接続メソッドが呼び出されます。

2.検証を接続するためのメソッドが単一の例外をスローしました。これはコレクションに追加されます。
3.メソッドは複数の例外をスローしました:コレクションと結合します。
4.メソッドはジェネレーターです。生成されるすべて(Throwable)はコレクションに追加されます。

これらのすべての操作の後、検証エラーのコレクションが空ではないことが判明した場合、それは破棄されます。 その後、どこかでそれを見つけて、これらすべての間違いをどうするかを決める必要があります。

衛生方法


さて、ここでの話は検証ほどエキサイティングではありません。 簡単です:

 class SanitizationExampleClass extends Std { protected function sanitizePhone($val) { return preg_replace('~\D~', '', $val); } } $obj = new SanitizationExampleClass; $obj->phone = '+7 (900) 123-45-67'; assert('79001234567' === $obj->phone); 

メソッドを定義しました。プロパティに割り当てる値を入力で受け取り、返されるものが実際に割り当てられます。 控えめですが、便利です。

小さな発表


もちろん、検証と衛生のテーマは、標準オブジェクトの「魔法の」方法に尽きることはありません。 次の記事の1つは、runn / validationライブラリに完全に専念します。これは現在、公開の準備中です。

そして最後に、約束された必須フィールド


最も重要なことは、あなたに言います。 特に、複雑な(「e」に重点を置いてこの言葉を言いたい:「複雑」)オブジェクトのトピックに移るとき。 しかし、それらがなくてもすべてを理解できます。

 class testClassWithRequired extends Std { protected static $required = ['foo', 'bar']; //     ,    getRequiredKeys()    } try { $obj = new testClassWithRequired(); } catch (Exceptions $errors) { assert(2 == count($errors)); assert('Required property "foo" is missing' === $errors[0]->getMessage()); assert('Required property "bar" is missing' === $errors[1]->getMessage()); } 

ご覧のとおり、ここでは、オブジェクトのコンストラクターでいくつかの必須フィールドが未定義であることが判明したことを通知するために、同じ使い慣れたマルチ除外メカニズムがここで使用されています。 ところで、そこで検証エラーが発生した場合は、それらも表示されます! 同じ$ errorsコレクションにすべて。

今日は以上です。 次の記事をお楽しみに!

PSフレームワーク全体のリリース日に関する詳細な計画はありません。また、次の日付に間に合うことを望んでいません。 したがって、いつ尋ねないでください。 個々のライブラリの準備ができ次第、それらに関する記事が公開されます。

PPSプライベートメッセージのエラーやタイプミスに関する情報を受け入れてくれて感謝しています。

素晴らしい週末をお過ごしください!

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


All Articles