タイプセーフ入力処理用の小さなPHPライブラリ。
一部のエンティティをリストするアクションがあるとしましょう。これには、エンティティが作成されるまでにページング、昇順または降順の注文、およびオプションのフィルタリングが含まれます。このアクションには、何らかの入力解析があります。これは次のようになります。
public function index ()
{
$ page = $ this -> request -> query -> get ( ' page ' );
if ( $ page === null || ! is_integer ( $ page )) {
throw new Exception ( " Parameter page not found " );
}
$ order = $ this -> request -> query -> get ( ' order ' );
if ( $ order === null || ! in_array ( $ order , [ ' asc ' , ' desc ' ])) {
throw new Exception ( " Parameter order not found " );
}
// Optional parameter
$ createdAt = $ this -> query -> query -> get ( ' createdAt ' );
if ( is_string ( $ createdAt )) {
$ createdAt = new DateTime ( $ createdAt );
} else {
$ createdAt = null ;
}
}明らかに、このコードはそれほど説明的ではないので読むのはあまり良くありません。それはまた、それが何をしているかについてかなり冗長です。そして、あなたが細心の注意を払わないとき、あなたはおそらくヌルチェックまたはタイプチェックを見逃すでしょう。
次に、上記のコードをこのバージョンと比較します。
public function index ()
{
$ page = $ this -> queryParameter ( ' page ' )-> int ()-> required ();
$ order = $ this -> queryParameter ( ' order ' )-> oneOf ([ ' asc ' , ' desc ' ])-> required ();
$ createdAt = $ this -> queryParameter ( ' createdAt ' )-> dateTime ()-> defaultsTo ( null );
}それがこのライブラリが提供するものです。 「このアクションにはタイプintのページパラメーターが必要」または「このアクションには、型dateTimeのオプションのパラメーターが作成され、不在の場合はデフォルト値に設定されます」を表現できます。
今すぐコードに直接移動したい場合は、例を挙げて遊ぶことができます。
cd /tmpgit clone [email protected]:mpscholten/request-parser.gitcd request-parsercomposer installcd examplesphp -S localhost:8080例ディレクトリ内には、他のいくつかのPHPファイルもあります。手を汚すために、例を少し変更することをお勧めします。
Composer経由でインストールします
composer require mpscholten/request-parser
symfony/http-foundationを使用している場合は、ここをクリックしてください。ServerRequestInterface実装を使用している場合は、ここをクリックしてください。Request抽象化(または単に古い$_GET and Friends)を使用している場合は、この例をご覧ください。 次の例では、Symfony Requestを使用していると仮定しています。
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ this -> initRequestParser ( $ request );
}
}次に、このようなライブラリを使用できます。
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ this -> initRequestParser ( $ request );
}
public function myAction ()
{
$ someParameter = $ this -> queryParameter ( ' someParameter ' )-> string ()-> required ();
}
} GET /MyController/myAction?someParameter=example実行する場合、 $someParameter変数には文字列"example"が含まれます。
GET /MyController/myActionのように、 ?someParameter部分を除外したときに何が起こるのだろうと思うかもしれません。この場合$this->queryParameter('someParameter')->string()->required() NotFoundExceptionをスローします。この例外は、エラーメッセージを表示するためにアプリケーションによって処理できます。
例を見てください。
次の例は、PSR7 ServerRequestInterfaceを使用していると仮定しています。
class MyController
{
use MPScholten RequestParser Psr7 ControllerHelperTrait;
public function __construct ( ServerRequestInterface $ request )
{
$ this -> initRequestParser ( $ request );
}
}次に、このようなライブラリを使用できます。
class MyController
{
use MPScholten RequestParser Psr7 ControllerHelperTrait;
public function __construct ( ServerRequestInterface $ request )
{
$ this -> initRequestParser ( $ request );
}
public function myAction ()
{
$ someParameter = $ this -> queryParameter ( ' someParameter ' )-> string ()-> required ();
}
} GET /MyController/myAction?someParameter=example実行する場合、 $someParameter変数には文字列"example"が含まれます。
GET /MyController/myActionのように、 ?someParameter部分を除外したときに何が起こるのだろうと思うかもしれません。この場合$this->queryParameter('someParameter')->string()->required() NotFoundExceptionをスローします。この例外は、エラーメッセージを表示するためにアプリケーションによって処理できます。
例を見てください。
someParameterオプションにするために、 required() defaultsTo($someDefaultValue)に置き換えることができます。
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ this -> initRequestParser ( $ request );
}
public function myAction ()
{
$ someParameter = $ this -> queryParameter ( ' someParameter ' )-> string ()-> defaultsTo ( ' no value given ' );
}
} GET /MyController/myAction実行すると、 $someParameter変数には"no value given"文字列が含まれます。デフォルト値を指定したため、例外はスローされません。
一般に、最初にパラメーター名を指定し、次にタイプを指定し、次にパラメーターが必要かどうかを指定します。
その他の例については、このリポジトリのexamples/ディレクトリをご覧ください。いくつかの実行可能な例が含まれています。
多くの場合、文字列以上のものが必要です。 RequestParserは、他のデータ型のメソッドも提供します。
class DashboardController
{
public function show ()
{
$ dashboardId = $ this -> queryParameter ( ' id ' )-> int ()-> required ();
// GET /dashboard?name=Hello => $dashboardName == "Hello"
$ dashboardName = $ this -> queryParameter ( ' name ' )-> string ()-> required ();
// Get /dashboard?name= => $dashboardName == "default value"
$ dashboardName = $ this -> queryParameter ( ' name ' )-> string ()-> defaultsToIfEmpty ( " default value " );
// GET /dashboard?status=private => $dashboardStatus == "private"
// GET /dashboard?status=public => $dashboardStatus == "public"
// GET /dashboard?status=invalid => A NotFoundException will be thrown
$ dashboardStatus = $ this -> queryParameter ( ' status ' )-> oneOf ([ ' private ' , ' public ' ])-> required ();
// GET /dashboard?createdAt=01.01.2016 => $dateTime == new DateTime("01.01.2016")
// GET /dashboard?createdAt=invalid_date => A NotFoundException will be thrown
$ dateTime = $ this -> queryParameter ( ' createdAt ' )-> dateTime ()-> required ();
// GET /dashboard?config={"a":true} => $json == ['a' => true]
$ json = $ this -> queryParameter ( ' config ' )-> json ()-> required ();
// GET /dashboard?includeWidgets=true => $includeWidgets == true
// GET /dashboard?includeWidgets=false => $includeWidgets == false
// GET /dashboard?includeWidgets=0 => $includeWidgets == false
// GET /dashboard?includeWidgets=abcde => A NotFoundException will be thrown
$ includeWidgets = $ this -> queryParameter ( ' includeWidgets ' )-> boolean ()-> required ();
// GET /dashboard?includeWidgets=yes => $includeWidgets == true
// GET /dashboard?includeWidgets=no => $includeWidgets == false
$ includeWidgets = $ this -> queryParameter ( ' includeWidgets ' )-> yesNoBoolean ()-> required ();
// GET /image?scale=2.5 => $scale == 2.5
$ scale = $ this -> queryParameter ( ' scale ' )-> float ()-> required ();
}
}これらのタイプはすべて、 defaultsToバリアントも提供します。
| タイプ | コードの例 | 入力例 |
|---|---|---|
| 弦 | $this->queryParameter('name')->string()->required(); | 'John Doe' |
| コンマ分離された文字列 | $this->queryParameter('names')->commaSeparated()->string()->required(); | 'John Doe,John Oliver' |
| 整数 | $this->queryParameter('id')->int()->required(); | '5' |
| コンマ分離整数 | $this->queryParameter('groupIds')->commaSeparated()->int()->required(); | '5,6,7,8' |
| フロート | $this->queryParameter('ratio')->float()->required(); | '0.98' |
| コンマ分離フロート | $this->queryParameter('precipitation')->commaSeparated()->float()->required(); | '0.98,1.24,5.21' |
| DateTime | $this->queryParameter('timestamp')->dateTime()->required(); | '2016-07-20' |
| コンマ分離された日時 | $this->queryParameter('eventTimes')->commaSeparated()->dateTime()->required(); | '2016-07-20 13:10:50,2016-07-21 12:01:07' |
| ブール | $this->queryParameter('success')->boolean()->required(); | 'true' |
| コンマ分離ブーリアン | $this->queryParameter('answers')->commaSeparated()->boolean()->required(); | '1,0,0,1' |
| はい/いいえブールン | $this->queryParameter('success')->yesNoBoolean()->required(); | 'yes' |
| コンマ分離されたYES/NOブール | $this->queryParameter('answers')->commaSeparated()->yesNoBoolean()->required(); | 'y,n,n,y,n' |
| JSON | $this->queryParameter('payload')->json()->required(); | '{"event":"click","timestamp":"2016-07-20 13:10:50"}' |
| コンマ分離されたJSON | $this->queryParameter('events')->commaSeparated()->json()->required(); | '{"event":"click","timestamp":"2016-07-20 13:10:50"},{"event":"add_to_basket","timestamp":"2016-07-20 13:11:01"}' |
$this->queryParameter($name)クエリパラメーター(「?」の後のすべてがクエリ文字列と呼ばれる)が必要であることをコントローラーに伝えます。これは通常、Get Requestsを扱うときに私たちが望むものです
POSTリクエストを扱っている場合、 $this->bodyParameter($name)を使用して、フォームフィールドまたはAjaxペイロードにアクセスする必要があります。
ライブラリを使用すると、IDEのオートコンプリート機能を広範囲に使用できます。たとえば、 $this->queryParameter('someParameter)->あなたのIDEを入力した後、IDEはすべての可能な入力型、例えばstring()またはint()を提供します。タイプ、eg string()を選択した後、IDEはrequired()またはdefaultsTo(defaultValue)を提供して、パラメーターが設定されていないときに動作を指定します。



ライブラリは、IDEによる静的分析をサポートしています。たとえば$createdAt = $this->queryParameter('createdAt')->dateTime()->required();のようなパラメーターを持っている場合、IDEは、 $createdAtがDateTimeオブジェクトであることを知っています。これにより、編集中にタイプエラーを検出することができ、タイプが読みやすさを改善するため、アクションのメンテナンスコストも削減できます。
ライブラリは、パラメーターには常に明示的なデフォルト値があるか、必要であるため、予期しないヌル値のリスクも減少します。
パラメーターが必要であるが見つからない場合、または検証が失敗した場合、ライブラリは例外をスローします。デフォルトの例外はMPScholtenRequestParserNotFoundExceptionおよびMPScholtenRequestParserInvalidValueExceptionです。ライブラリによって投げられたエラーを処理するための提案された方法は、フロントコントローラー内でそれらをキャッチすることです。
try {
$ controller -> $ action ();
} catch ( NotFoundException $ e ) {
echo $ e -> getMessage ();
} catch ( InvalidValueException $ e ) {
echo $ e -> getMessage ();
} class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ exceptionFactory = new ExceptionFactory (CustomNotFoundException::class, CustomInvalidValueException::class));
$ config = new MPScholten RequestParser Config ();
$ config -> setExceptionFactory ( $ exceptionFactory );
$ this -> initRequestParser ( $ request , $ config );
}
}ライブラリによってスローされた例外メッセージを1回または2回オーバーライドする必要がある場合は、最初と2番目の引数として例外メッセージを->required()に渡すことでこれを行うことができます。
class DashboardController
{
public function show ()
{
$ dashboardId = $ this -> queryParameter ( ' id ' )-> int ()-> required ( " The dashboard id has to be a valid number " , " No dashboard id given " );
}
}すべてのアクションにカスタム例外メッセージを指定したくないが、組み込みの例外メッセージを使用したくない場合は、独自の例外メッセージジェネレーターを提供できます。
class FriendlyExceptionMessageFactory extends MPScholten RequestParser ExceptionMessageFactory
{
protected function createNotFoundMessage ( $ parameterName )
{
return " Looks like $ parameterName is missing :) " ;
}
protected function createInvalidValueMessage ( $ parameterName , $ parameterValue , $ expected )
{
return " Whoops :) $ parameterName seems to be invalid. We're looking for $ expected but you provided ' $ parameterValue ' " ;
}
}
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ config = new MPScholten RequestParser Config ();
$ config -> setExceptionMessageFactory ( new FriendlyExceptionMessageFactory ());
$ this -> initRequestParser ( $ request , $ config );
}
}カスタムの例外についてこの例を確認してください。
絶対に。このライブラリは当初、五分位で開発され、2015年4月以来生産で広範囲に使用されています。生産で大規模に使用することは、後方互換性と壊れないことに大きな焦点があることを意味します。
composer tests
composer tests-coverage
プルリクエストをお気軽に送信してください!