Perpustakaan PHP kecil untuk penanganan input jenis-aman.
Katakanlah Anda memiliki tindakan yang mencantumkan beberapa entitas. Ini termasuk paging, memesan atau turun pemesanan dan penyaringan opsional pada saat entitas dibuat. Tindakan ini akan memiliki semacam penguraian input, yang bisa terlihat seperti ini:
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 ;
}
}Jelas kode ini tidak terlalu bagus untuk dibaca karena tidak terlalu deskriptif. Ini juga cukup bertele -tele untuk apa yang dilakukannya. Dan ketika Anda tidak memperhatikan, Anda mungkin akan melewatkan cek nol atau cek jenis.
Sekarang bandingkan kode di atas dengan versi ini:
public function index ()
{
$ page = $ this -> queryParameter ( ' page ' )-> int ()-> required ();
$ order = $ this -> queryParameter ( ' order ' )-> oneOf ([ ' asc ' , ' desc ' ])-> required ();
$ createdAt = $ this -> queryParameter ( ' createdAt ' )-> dateTime ()-> defaultsTo ( null );
}Itulah yang ditawarkan perpustakaan ini. Ini memungkinkan Anda untuk mengekspresikan " Tindakan ini memerlukan parameter halaman tipe int " atau " Tindakan ini memiliki parameter opsional yang dibuat dari tipe datetime, dan akan diatur ke nilai default jika tidak ada ".
Jika Anda ingin langsung ke kode sekarang, Anda bisa bermain -main dengan contoh -contohnya.
cd /tmpgit clone [email protected]:mpscholten/request-parser.gitcd request-parsercomposer installcd examplesphp -S localhost:8080Ada juga beberapa file PHP lainnya di dalam direktori contoh. Untuk membuat tangan Anda kotor, saya sarankan hanya memodifikasi contoh sedikit.
Instal melalui komposer
composer require mpscholten/request-parser
symfony/http-foundation , klik di sini.ServerRequestInterface , klik di sini.Request lain (atau mungkin hanya $_GET dan teman -teman lama), lihat contoh ini. Contoh berikut mengasumsikan Anda menggunakan Request Symfony:
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ this -> initRequestParser ( $ request );
}
}Maka Anda dapat menggunakan perpustakaan seperti ini:
class MyController
{
use MPScholten RequestParser Symfony ControllerHelperTrait;
public function __construct ( Request $ request )
{
$ this -> initRequestParser ( $ request );
}
public function myAction ()
{
$ someParameter = $ this -> queryParameter ( ' someParameter ' )-> string ()-> required ();
}
} Saat melakukan GET /MyController/myAction?someParameter=example , variabel $someParameter akan berisi string "example" .
Anda mungkin bertanya -tanya apa yang terjadi ketika kita meninggalkan bagian ?someParameter , seperti GET /MyController/myAction . Dalam hal ini $this->queryParameter('someParameter')->string()->required() akan melempar NotFoundException . Pengecualian ini dapat ditangani oleh aplikasi Anda untuk menampilkan pesan kesalahan.
Lihatlah contoh -contohnya.
Contoh berikut mengasumsikan Anda menggunakan PSR7 ServerRequestInterface :
class MyController
{
use MPScholten RequestParser Psr7 ControllerHelperTrait;
public function __construct ( ServerRequestInterface $ request )
{
$ this -> initRequestParser ( $ request );
}
}Maka Anda dapat menggunakan perpustakaan seperti ini:
class MyController
{
use MPScholten RequestParser Psr7 ControllerHelperTrait;
public function __construct ( ServerRequestInterface $ request )
{
$ this -> initRequestParser ( $ request );
}
public function myAction ()
{
$ someParameter = $ this -> queryParameter ( ' someParameter ' )-> string ()-> required ();
}
} Saat melakukan GET /MyController/myAction?someParameter=example , variabel $someParameter akan berisi string "example" .
Anda mungkin bertanya -tanya apa yang terjadi ketika kita meninggalkan bagian ?someParameter , seperti GET /MyController/myAction . Dalam hal ini $this->queryParameter('someParameter')->string()->required() akan melempar NotFoundException . Pengecualian ini dapat ditangani oleh aplikasi Anda untuk menampilkan pesan kesalahan.
Lihatlah contoh -contohnya.
Untuk membuat someParameter opsional, kita bisa mengganti required() dengan 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 ' );
}
} Saat melakukan GET /MyController/myAction , variabel $someParameter sekarang akan berisi string "no value given" . Tidak ada pengecualian yang akan dilemparkan karena kami menentukan nilai default.
Secara umum Anda pertama -tama menentukan nama parameter, diikuti oleh tipe dan kemudian menentukan apakah parameter diperlukan atau opsional dengan nilai default.
Untuk contoh lebih lanjut, lihat examples/ direktori repositori ini. Ini berisi beberapa contoh yang dapat dijalankan.
Seringkali kita membutuhkan lebih dari sekedar string. RequestParser juga menyediakan metode untuk tipe data lainnya:
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 ();
}
} Semua jenis ini juga memberikan varian defaultsTo .
| Jenis | Contoh Kode | Contoh input |
|---|---|---|
| Rangkaian | $this->queryParameter('name')->string()->required(); | 'John Doe' |
| String yang dipisahkan koma | $this->queryParameter('names')->commaSeparated()->string()->required(); | 'John Doe,John Oliver' |
| Bilangan bulat | $this->queryParameter('id')->int()->required(); | '5' |
| Integer yang dipisahkan koma | $this->queryParameter('groupIds')->commaSeparated()->int()->required(); | '5,6,7,8' |
| Mengambang | $this->queryParameter('ratio')->float()->required(); | '0.98' |
| Pelampung yang dipisahkan koma | $this->queryParameter('precipitation')->commaSeparated()->float()->required(); | '0.98,1.24,5.21' |
| Datetime | $this->queryParameter('timestamp')->dateTime()->required(); | '2016-07-20' |
| Datetime yang dipisahkan secara koma | $this->queryParameter('eventTimes')->commaSeparated()->dateTime()->required(); | '2016-07-20 13:10:50,2016-07-21 12:01:07' |
| Boolean | $this->queryParameter('success')->boolean()->required(); | 'true' |
| Boolean yang dipisahkan koma | $this->queryParameter('answers')->commaSeparated()->boolean()->required(); | '1,0,0,1' |
| Ya/Tidak Boolean | $this->queryParameter('success')->yesNoBoolean()->required(); | 'yes' |
| Dipisahkan secara koma ya/tidak boolean | $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 yang dipisahkan koma | $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) memberi tahu controller bahwa kami menginginkan parameter kueri (semuanya setelah "?" Disebut string kueri). Ini biasanya yang kami inginkan saat berhadapan dengan permintaan mendapatkan
Saat kita berurusan dengan permintaan pos, kita perlu menggunakan $this->bodyParameter($name) untuk mengakses bidang formulir atau payload Ajax.
Perpustakaan memungkinkan Anda untuk menggunakan fitur pelengkapan autocompetion yang luas dari IDE Anda. Misalnya setelah mengetik $this->queryParameter('someParameter)-> IDE Anda akan menawarkan semua jenis input yang mungkin, misalnya string() atau int() . Setelah memilih jenis, misalnya string() , IDE Anda akan menawarkan required() atau defaultsTo(defaultValue) untuk menentukan perilaku ketika parameter tidak diatur.



Perpustakaan mendukung analisis statis oleh IDE Anda. Misalnya saat memiliki parameter seperti $createdAt = $this->queryParameter('createdAt')->dateTime()->required(); , IDE Anda akan tahu bahwa $createdAt adalah objek DateTime . Ini memungkinkan Anda untuk mendeteksi kesalahan jenis saat mengedit dan juga mengurangi biaya pemeliharaan suatu tindakan karena jenis meningkatkan keterbacaan.
Perpustakaan juga mengurangi risiko nilai nol yang tidak terduga karena parameter selalu memiliki nilai default eksplisit atau diperlukan.
Ketika parameter diperlukan tetapi tidak ditemukan atau ketika validasi gagal, perpustakaan akan melempar pengecualian. Pengecualian default adalah MPScholtenRequestParserNotFoundException dan MPScholtenRequestParserInvalidValueException . Cara yang disarankan untuk menangani kesalahan yang dilemparkan oleh perpustakaan adalah dengan menangkap mereka di dalam pengontrol depan Anda:
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 );
}
} Jika Anda perlu mengganti pesan pengecualian yang dilemparkan oleh perpustakaan hanya sekali atau dua kali, Anda dapat melakukan ini dengan menyampaikan pesan pengecualian sebagai argumen pertama dan kedua untuk ->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 " );
}
}Jika Anda tidak ingin menentukan pesan pengecualian khusus untuk semua tindakan Anda, tetapi masih tidak ingin menggunakan pesan pengecualian bawaan, Anda dapat memberikan generator pesan pengecualian Anda sendiri:
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 );
}
}Lihat contoh ini tentang pengecualian khusus.
Sangat. Perpustakaan ini awalnya dikembangkan di Quintly dan banyak digunakan dalam produksi sejak April 2015. Menggunakannya pada skala dalam produksi berarti ada fokus besar AA pada kompatibilitas ke belakang dan tidak memecahkan barang.
composer tests
composer tests-coverage
Jangan ragu untuk mengirim permintaan tarik!