diff --git a/README.md b/README.md index f1539d3..5aa3aeb 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,16 @@ Install via composer composer require mpscholten/request-parser ``` -If you're using the `symfony/http-foundation` `Request`, you just need to import a trait into your controller. If you're using some other `Request` abstraction (or maybe just plain old `$_GET` and friends), [check out this example](https://github.com/mpscholten/request-parser/blob/master/examples/not-symfony.php). -The following example asumes you're using the symfony `Request`: +**Integrations:** + + - If you're using `symfony/http-foundation`, [click here](#symfony-httpfoundation). + - If you're using a Psr7 `ServerRequestInterface` implementation, [click here](#psr7). + - If you're using some other `Request` abstraction (or maybe just plain old `$_GET` and friends), [check out this example](https://github.com/mpscholten/request-parser/blob/master/examples/not-symfony.php). + +#### Symfony HttpFoundation + +The following example assumes you're using the symfony `Request`: ```php class MyController @@ -112,6 +119,48 @@ be handled by your application to show an error message. Take a look at [the examples](https://github.com/mpscholten/request-parser/tree/master/examples). +#### Psr7 + +The following example assumes you're using the Psr7 `ServerRequestInterface`: + +```php +class MyController +{ + use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; + + public function __construct(ServerRequestInterface $request) + { + $this->initRequestParser($request); + } +} +``` + +Then you can use the library like this: +```php +class MyController +{ + use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; + + public function __construct(ServerRequestInterface $request) + { + $this->initRequestParser($request); + } + + public function myAction() + { + $someParameter = $this->queryParameter('someParameter')->string()->required(); + } +} +``` + +When doing `GET /MyController/myAction?someParameter=example`, the `$someParameter` variable will contain the string `"example"`. + +You might wonder what happens when we leave out the `?someParameter` part, like `GET /MyController/myAction`. In this case the +`$this->queryParameter('someParameter')->string()->required()` will throw a `NotFoundException`. This exception can +be handled by your application to show an error message. + +Take a look at [the examples](https://github.com/mpscholten/request-parser/tree/master/examples). + #### Optional Parameters To make the `someParameter` optional, we can just replace `required()` with `defaultsTo($someDefaultValue)`: diff --git a/composer.json b/composer.json index ad64487..438e93c 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,9 @@ "require": {}, "require-dev": { "phpunit/phpunit": "3.7.*", - "symfony/http-foundation": "3.1.*" + "symfony/http-foundation": "3.1.*", + "symfony/psr-http-message-bridge": "^0.2.0", + "zendframework/zend-diactoros": "^1.3" }, "autoload": { "psr-4": {"MPScholten\\RequestParser\\": "src/"} diff --git a/examples/not-symfony.php b/examples/not-symfony.php index eca623d..1e5d2be 100644 --- a/examples/not-symfony.php +++ b/examples/not-symfony.php @@ -12,45 +12,60 @@ require __DIR__ . '/../vendor/autoload.php'; -trait CustomControllerHelperTrait +class CustomRequestParserFactory implements \MPScholten\RequestParser\RequestParserFactory { - private $queryParser; - private $bodyParser; + /** + * @var array + */ + private $request; + private $exceptionFactory; + + public function __construct(array $request, $exceptionFactory) + { + $this->request = $request; + $this->exceptionFactory = $exceptionFactory; + } - protected final function initRequestParser() + public function createQueryParser() { - $this->queryParser = new MPScholten\RequestParser\RequestParser( + return new MPScholten\RequestParser\RequestParser( function ($parameterName) { - if (isset($_GET[$parameterName])) { - return $_GET[$parameterName]; + if (isset($this->request[$parameterName])) { + return $this->request[$parameterName]; } return null; }, - null + $this->exceptionFactory ); - $this->bodyParser = new MPScholten\RequestParser\RequestParser( + } + + public function createBodyParser() + { + return new MPScholten\RequestParser\RequestParser( function ($parameterName) { - if (isset($_POST[$parameterName])) { - return $_POST[$parameterName]; + if (isset($this->request[$parameterName])) { + return $this->request[$parameterName]; } return null; }, - null + $this->exceptionFactory ); } +} - protected function queryParameter($name) - { - return $this->queryParser->get($name); - } +trait CustomControllerHelperTrait +{ + use \MPScholten\RequestParser\BaseControllerHelperTrait; - protected function bodyParameter($name) + /** + * Will be called during the `initRequestParser()` call in `MyController` + */ + protected final function createRequestParserFactory($request, $exceptionFactory) { - return $this->bodyParser->get($name); + return new CustomRequestParserFactory($request, $exceptionFactory); } - } class MyController @@ -59,7 +74,13 @@ class MyController public function __construct() { - $this->initRequestParser(); + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $request = $_GET; + } else { + $request = $_POST; + } + + $this->initRequestParser($request); } public function hello() diff --git a/examples/psr7.php b/examples/psr7.php new file mode 100644 index 0000000..bca0e48 --- /dev/null +++ b/examples/psr7.php @@ -0,0 +1,62 @@ +createRequest($symfonyRequest); + +class MyController +{ + use ControllerHelperTrait; + + public function __construct(ServerRequestInterface $request) + { + $this->initRequestParser($request); + } + + public function hello() + { + $name = $this->queryParameter('name')->string()->required(); + + return "Hello $name"; + } + + public function helloWithDefault() + { + $name = $this->queryParameter('name')->string()->defaultsTo('unknown'); + + return "Hello $name"; + } + + public function json() + { + $payload = $this->queryParameter('payload')->json()->required(); + + return print_r($payload, true); + } +} + +$controller = new MyController($request); +$action = $request->getQueryParams()['action']; + +try { + echo $controller->$action(); +} catch (\MPScholten\RequestParser\NotFoundException $e) { + echo $e->getMessage(); +} diff --git a/src/BaseControllerHelperTrait.php b/src/BaseControllerHelperTrait.php new file mode 100644 index 0000000..491695d --- /dev/null +++ b/src/BaseControllerHelperTrait.php @@ -0,0 +1,50 @@ +createRequestParserFactory($request, $exceptionFactory); + $this->queryParser = $requestParserFactory->createQueryParser(); + $this->bodyParser = $requestParserFactory->createBodyParser(); + } + + /** + * Use this method to access the query parameters of the request. + * + * $page = $this->queryParameter('page')->int()->defaultsTo(0) + * + * @param string $name + * @return TypeParser + */ + protected function queryParameter($name) + { + return $this->queryParser->get($name); + } + + /** + * Use this method to access the body parameters of the request (e.g. $_POST). + * + * $password = $this->bodyParameter('password')->string()->required() + * + * @param string $name + * @return TypeParser + */ + protected function bodyParameter($name) + { + return $this->bodyParser->get($name); + } +} diff --git a/src/Psr7/ControllerHelperTrait.php b/src/Psr7/ControllerHelperTrait.php new file mode 100644 index 0000000..e48fac0 --- /dev/null +++ b/src/Psr7/ControllerHelperTrait.php @@ -0,0 +1,15 @@ +request = $request; + $this->exceptionFactory = $exceptionFactory; + } + + public function createQueryParser() + { + $query = $this->request->getQueryParams(); + + $readParameter = function ($name) use ($query) { + if (!isset($query[$name])) { + return null; + } + + return $query[$name]; + }; + + return new RequestParser($readParameter, $this->exceptionFactory); + } + + public function createBodyParser() + { + $body = $this->request->getParsedBody(); + + $readParameter = function ($name) use ($body) { + if (!isset($body[$name])) { + return null; + } + + return $body[$name]; + }; + + return new RequestParser($readParameter, $this->exceptionFactory); + } +} diff --git a/src/RequestParserFactory.php b/src/RequestParserFactory.php new file mode 100644 index 0000000..17eeb78 --- /dev/null +++ b/src/RequestParserFactory.php @@ -0,0 +1,16 @@ +queryParser = $requestParser->createQueryParser(); - $this->bodyParser = $requestParser->createBodyParser(); - } - - /** - * Use this method to access the query parameters of the request. - * - * $page = $this->queryParameter('page')->int()->defaultsTo(0) - * - * @param string $name - * @return TypeParser - */ - protected function queryParameter($name) - { - return $this->queryParser->get($name); - } - - /** - * Use this method to access the body parameters of the request (e.g. $_POST). - * - * $password = $this->bodyParameter('password')->string()->required() - * - * @param string $name - * @return TypeParser - */ - protected function bodyParameter($name) + protected final function createRequestParserFactory($request, $exceptionFactory) { - return $this->bodyParser->get($name); + return new SymfonyRequestParserFactory($request, $exceptionFactory); } } diff --git a/src/Symfony/SymfonyRequestParser.php b/src/Symfony/SymfonyRequestParser.php index a37b689..8ae2a92 100644 --- a/src/Symfony/SymfonyRequestParser.php +++ b/src/Symfony/SymfonyRequestParser.php @@ -2,35 +2,9 @@ namespace MPScholten\RequestParser\Symfony; -use MPScholten\RequestParser\RequestParser; -use Symfony\Component\HttpFoundation\Request; - -class SymfonyRequestParser +/** + * @deprecated This class got renamed to `SymfonyRequestParserFactory` + */ +class SymfonyRequestParser extends SymfonyRequestParserFactory { - private $request; - private $exceptionFactory; - - public function __construct(Request $request, $exceptionFactory = null) - { - $this->request = $request; - $this->exceptionFactory = $exceptionFactory; - } - - public function createQueryParser() - { - $readParameter = function ($name) { - return $this->request->query->get($name, null); - }; - - return new RequestParser($readParameter, $this->exceptionFactory); - } - - public function createBodyParser() - { - $readParameter = function ($name) { - return $this->request->request->get($name, null); - }; - - return new RequestParser($readParameter, $this->exceptionFactory); - } } diff --git a/src/Symfony/SymfonyRequestParserFactory.php b/src/Symfony/SymfonyRequestParserFactory.php new file mode 100644 index 0000000..8fd48bb --- /dev/null +++ b/src/Symfony/SymfonyRequestParserFactory.php @@ -0,0 +1,37 @@ +request = $request; + $this->exceptionFactory = $exceptionFactory; + } + + public function createQueryParser() + { + $readParameter = function ($name) { + return $this->request->query->get($name, null); + }; + + return new RequestParser($readParameter, $this->exceptionFactory); + } + + public function createBodyParser() + { + $readParameter = function ($name) { + return $this->request->request->get($name, null); + }; + + return new RequestParser($readParameter, $this->exceptionFactory); + } +} diff --git a/tests/Integration/Psr7IntegrationTest.php b/tests/Integration/Psr7IntegrationTest.php new file mode 100644 index 0000000..bbf5a3b --- /dev/null +++ b/tests/Integration/Psr7IntegrationTest.php @@ -0,0 +1,89 @@ + 'Test', + 'int' => 1 + ]; + + $request = (new Zend\Diactoros\ServerRequest()); + + $getRequest = $request + ->withMethod('GET') + ->withQueryParams($parameters); + + $postRequest = $request + ->withMethod('POST') + ->withParsedBody($parameters); + + return [ + [new Psr7Controller($getRequest)], + [new Psr7Controller($postRequest)] + ]; + } + + /** + * @dataProvider controllersProvider + */ + public function testStringAction(Psr7Controller $controller) + { + $this->assertEquals('Test', $controller->testString()); + } + + /** + * @dataProvider controllersProvider + */ + public function testIntAction(Psr7Controller $controller) + { + $this->assertEquals(1, $controller->testInt()); + } + + /** + * @dataProvider controllersProvider + */ + public function testNotFoundActionThrowsException(Psr7Controller $controller) + { + $this->setExpectedException(\MPScholten\RequestParser\NotFoundException::class, "Parameter notFound not found"); + $controller->testNotFound(); + } +} + +class Psr7Controller +{ + use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; + + private $request; + + public function __construct(Psr\Http\Message\ServerRequestInterface $request) + { + $this->initRequestParser($request); + $this->request = $request; + } + + protected function parameter($name) + { + if ($this->request->getMethod() === 'GET') { + return $this->queryParameter($name); + } else { + return $this->bodyParameter($name); + } + } + + public function testString() + { + return $this->parameter('string')->string()->required(); + } + + public function testInt() + { + return $this->parameter('int')->int()->required(); + } + + public function testNotFound() + { + return $this->parameter('notFound')->string()->required(); + } +}