PHPのカスタムタイプ

プログラムが外部から受信するデータに関しては、trustno1の規則に従うことが慣習となっています。 これは、ユーザーから直接受信したデータだけでなく、クライアントコードがルーチンに渡すデータにも当てはまります。



PHP 7には、クラスだけでなくスカラーも含む高度な引数型制御システムが装備されています。 ただし、複雑なデータ構造に関しては何も変更されていません。PHPには何でも含めることができる配列のタイプは1つだけです。



PHPの新しいバージョンが状況を修正することを願っています。 そして現時点では、この分野における私のベストプラクティスのいくつかをコミュニティと共有したいと思っています。



画像



alexeymaximov / fulltype

alexeymaximov /含有物



UPD 12/02/2018-提供されているドキュメントとライブラリの現在のバージョンが一致するように、出版物が更新されました。



フルタイプ



GitHub: alexeymaximov / fulltype



このライブラリは、型を扱うために特別に設計されています。 ArsMnemonica \ Fulltype \ fulltype :: define関数を使用して、独自のデータ型を定義できます。



function define(string $aName, TypeInterface $aType): TypeInterface;
      
      





ArsMnemonica \ Fulltype \ TypeInterfaceインターフェースを実装する独自のクラスを作成してインスタンス化するか、組み込みのものを使用できます。



関数ArsMnemonica \ Fulltype \ fulltype :: typeは、タイプアクセスすることを目的としています



 function type(string $aName): TypeInterface;
      
      





型名を引数(定義関数のaName引数)として受け取り、対応するオブジェクトを返します。



型に対して値を確認するには、関数ArsMnemonica \ Fulltype \ fulltype :: isを使用します。



 function is($aValue, TypeInterface $aType): bool;
      
      





または、タイプオブジェクト自体のvalidateメソッドによって:



 function TypeInterface::validate($aValue): bool;
      
      





型の一致の値を確認するには、 ArsMnemonica \ Fulltype \ fulltype :: assert関数を使用することもできます。



 function assert($aValue, TypeInterface $aType): mixed;
      
      





この関数は、チェックに成功した場合に渡された値$ aValueを返すか、TypeErrorから継承された例外をスローします。メッセージには、渡された値の説明と関数assertの呼び出し場所が含まれます。



次の組み込み型が定義されています( ArsMnemonica \ Fulltype名前空間fulltypeクラス):



 function bool(): BooleanType;
      
      





ブール値はtrue / falseです。



 function number(float $aMin = null, float $aMax = null): NumericType; function int(int $aMin = null, int $aMax = null): IntegerType; function cardinal(int $aMax = null): CardinalType;
      
      





数値タイプ。



NumericType型は、PHPのint型とfloat型に対応しています。



後継であるIntegerType型は、PHP型intにのみ対応します。



どちらのタイプも最小値と最大値に制限できます。



IntTypeの後継であるCardinalTypeタイプは、定量的な数値(符号なし整数)に対応します-最小値は0で、最大値を決定できます。



 function string(int $aLength = null): StringType;
      
      





文字列型。最大長によって制限される場合があります。



 function regexp(string $aRegularExpression): RegularExpressionType;
      
      





正規表現。



 function enum(...$aValues): EnumerableType;
      
      





列挙型。



有効な値のセットを特定のセットに制限します。



 function object(string $aBase = null): ObjectType;
      
      





オブジェクトの種類。



値は、指定されたクラスのオブジェクトのみになります(インターフェイスも有効です)。



 function null(TypeInterface $aType): NullableType;
      
      





Nullableタイプ。



子タイプの有効な値のセットをnullで補完します。



 function array(int $aLength = null): ArrayType;
      
      





大規模タイプ(キーワード配列は関数名として有効ではありません)は、最大長によって制限される場合があります。



値は次のとおりです。

-配列;

-ArrayAccess、Countable、およびTraversableインターフェイスを実装するオブジェクト( 目的のメソッドを呼び出す必要があります)。



有効な配列値のタイプを指定するには、 of(TypeInterface)メソッドを使用し、キーの場合はby(TypeInterface)メソッドを使用します。 PHPのintおよびstring型とは異なるキー型を指定すると、PHP配列は他の型のキーを持つことができないため、オブジェクトに対してのみ意味を持ちます。



 function any(TypeInterface ...$aTypes): MultipleType;
      
      





検証のために渡された値が子タイプの少なくとも1つと一致する必要がある構造タイプ。



 function union(TypeInterface ...$aTypes): ExclusiveType;
      
      





検証のために渡された値が子タイプの1つと一致することを必要とする構造タイプ。



 function struct(TypeInterface ...$aTypes): ComplexType;
      
      





検証のためにすべての子タイプに渡される値を必要とする構造タイプ。



このタイプでは、次の子タイプを指定するのが理にかなっています。



 function key(string $aName, TypeInterface $aType = null): PropertyType
      
      





キータイプ。検証に渡される値は、指定されたタイプの文字列キーを含む配列である必要があります。



 function offset(string $aName, TypeInterface $aType = null): PropertyType
      
      





検証のために渡された値が、指定されたタイプの文字列オフセットを含むArrayAccessインターフェイスを実装するオブジェクトまたは配列である必要があるオフセットタイプ。



 function property(string $aName, TypeInterface $aType = null): PropertyType
      
      





検証のために渡された値が、指定されたタイプのプロパティを含むオブジェクトである必要があるプロパティタイプ。



上記のタイプに対してオプションのメソッドが呼び出された場合、対応するチェックにより、そのようなキー/オフセット/プロパティが存在しないことが許可されます。



ライブラリの動作を示すために、次の例を検討してください。



 use ArsMnemonica\Fulltype\fulltype as t; const input_t = 'input'; t::define(input_t, t::struct( t::key('name', t::string()), t::key('authors', t::any( t::string(), t::array()->of(t::string()) )), t::union( t::key('text', t::string()), t::key('content', t::struct( t::key('title', t::string(255)), t::key✱('annotation', t::string(65535)), t::key('text', t::string()), t::key✱('pages', t::cardinal?(5000)) )) ), t::key('status', t::enum('WILL_READ', 'READ', 'FAVORITE_BOOK')) )); echo "Processing input...\n"; if (PHP_SAPI === 'cli') { $input = []; parse_str(implode('&', array_slice($argv, 1)), $input); } else { $input = $_GET; } foreach ($input as $key => $value) { echo "$key: " . json_encode($value) . "\n"; } echo "Validation: " . (t::is($input, t::type(input_t)) ? 'success' : 'failed') . PHP_EOL;
      
      





このコードは、ブックシリーズ要素の送信された説明の正確さをチェックします。





このような一連のパラメーターは有効です。



 name="The Lord of the Rings" authors[]="JRR Tolkien" content[title]="The Return of the King" content[text]=... status=READ
      
      





そして、これはテストに合格しません。



 name="The Lord of the Rings" authors[]="JRR Tolkien" text=... content[title]="The Return of the King" content[text]=... status=READ
      
      







結論の代わりに



これはある程度までは自転車のセットですが、仕事中の誰かに役立つことを願っています。 typedefは、json_decodeを使用した変換とともにスクリプトパラメーターをチェックするのに役立ちます。 また、既成のツールを使用して、引数の配列タイプを制限するためにコンテナが役立ちます。



オブジェクトの型付きプロパティを追加したり、パフォーマンスを改善するためにライブラリを拡張機能の形で配置したり、他に考えぬことをしたりすることもできますが、これまでのところ私はこれを緊急の必要とは考えていません。



画像



また、建設的な批判に耳を傾け、これらのシンプルなツールで何かを改善したり、私を通り過ぎた銀の弾丸について学んだりします。



ご清聴ありがとうございました!



All Articles