小型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 ;
}
}顯然,該代碼的閱讀不是很好,因為它不是很好的描述性。它在做什麼也很詳細。而且,當您不密切關注時,您可能會錯過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 require mpscholten/request-parser
symfony/http-foundation ,請單擊此處。ServerRequestInterface實現,請單擊此處。Request抽象(或者只是普通的舊$_GET和朋友),請查看此示例。 以下示例假設您正在使用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" 。
您可能會想知道當我們遺漏了?someParameter部分時會發生什麼,例如GET /MyController/myAction 。在這種情況下, $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" 。
您可能會想知道當我們遺漏了?someParameter部分時會發生什麼,例如GET /MyController/myAction 。在這種情況下, $this->queryParameter('someParameter')->string()->required()將拋出NotFoundException 。您的應用程序可以處理此例外,以顯示錯誤消息。
看看示例。
為了使someParameter可選,我們可以將defaultsTo($someDefaultValue)替換為required() :
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' |
| 逗號分隔是/否布爾 | $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)告訴控制器我們想要一個查詢參數(“?”之後的所有內容都稱為查詢字符串)。這通常是我們在處理獲得請求時想要的
當我們處理髮布請求時,我們需要使用$this->bodyParameter($name)訪問表單字段或AJAX有效載荷。
該庫允許您廣泛使用IDE的自動完成功能。例如,在鍵入$this->queryParameter('someParameter)->您的IDE將為您提供所有可能的輸入類型,例如string()或int() 。選擇類型後,例如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 );
}
}如果您只需要僅一次或兩次庫來覆蓋庫拋出的異常消息,則可以通過將異常消息作為第一個和第二個參數傳遞給->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 );
}
}查看有關自定義異常的示例。
絕對地。該圖書館最初是在Quintly開發的,自2015年4月以來一直在生產中廣泛使用。在生產中使用它,這意味著AA非常關注向後兼容性而不是破壞東西。
composer tests
composer tests-coverage
隨時發送拉動請求!