Skip to content

Commit 59c902d

Browse files
committed
[#1] - add parameter matching in actions (must be activated)
1 parent 2cec8a5 commit 59c902d

File tree

3 files changed

+128
-14
lines changed

3 files changed

+128
-14
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,32 @@ http://mysite.tld/test/action | \Project\Controller\Test::actio
5555
http://mysite.tld/also/work/with/full/path | \Project\Controller\Also\Work\With\Full::pathAction
5656
http://mysite.tld/my/normal | \Project\Controller\My::getNormalAction
5757
http://mysite.tld/my/normal (with HTTP post) | \Project\Controller\My::postNormalAction
58+
59+
## Parameter Matching
60+
61+
Since 0.6.0, you can use *"Parameter Matching"*
62+
63+
Simply activate it when dispatching :
64+
65+
```php
66+
require_once ('vendor/autoload.php');
67+
$nano = new \Nano\Framework();
68+
$nano->setParameterMatching->dispatch();
69+
```
70+
71+
And then you'll be able to use it like this :
72+
73+
```php
74+
<?php
75+
namespace \Project\Controller;
76+
77+
class MyAwesomeController
78+
{
79+
public function getHelloAction($age, $name)
80+
{
81+
echo "Hello $name, I'm {$age}yo"; //please, use this code for test only
82+
}
83+
}
84+
```
85+
86+
and call `http://mysite.tld/myawesomecontroller/hello?name=World&age=900` to display "Hello World, I'm 900yo" !

src/Framework.php

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php
2-
declare(strict_types = 1);
2+
declare(strict_types=1);
33

44
namespace Nano;
55

@@ -12,6 +12,7 @@ final class Framework
1212
private $projectNamespace = '\Project';
1313
private $controllerPackage = '\Controller';
1414
private $controllerActionSuffix = 'Action';
15+
private $withParameterMatching = false;
1516

1617
/**
1718
* Dispatch the request
@@ -21,27 +22,62 @@ final class Framework
2122
public function dispatch()
2223
{
2324
list($controllerName, $action) = $this->getControllerAndAction();
24-
$controller = $this->projectNamespace . $this->controllerPackage . '\\' . ucfirst($controllerName);
25-
if (!class_exists($controller)) {
26-
throw new \Exception('controller ' . $controllerName . ' not found');
27-
};
28-
$controller = new $controller;
25+
$controller = $this->getControllerFromName($controllerName);
2926
$finalAction = $this->getVerbFromRequest() . ucfirst($action) . $this->controllerActionSuffix;
3027
if (is_callable(array($controller, $finalAction))) {
31-
return $controller->$finalAction();
28+
return call_user_func_array(
29+
[$controller, $finalAction],
30+
$this->getParametersForMatching($controller, $finalAction)
31+
);
3232
}
3333
$finalAction = $action . $this->controllerActionSuffix;
3434
if (!is_callable(array($controller, $finalAction))) {
3535
throw new \Exception('action ' . $finalAction . ' not found in controller ' . $controllerName);
3636
}
37-
return $controller->$finalAction();
37+
return call_user_func_array(
38+
[$controller, $finalAction],
39+
$this->getParametersForMatching($controller, $finalAction)
40+
);
41+
}
42+
43+
/**
44+
* Returns parameters from request matching specified controller and action
45+
* @param object $controller
46+
* @param string $action
47+
* @return array
48+
*/
49+
private function getParametersForMatching($controller, string $action): array
50+
{
51+
$parameters = [];
52+
$reflection = new \ReflectionMethod($controller, $action);
53+
foreach ($reflection->getParameters() as $param) {
54+
if (isset($_REQUEST[$param->name])) {
55+
$parameters[$param->name] = $_REQUEST[$param->name];
56+
}
57+
}
58+
return $parameters;
59+
}
60+
61+
/**
62+
* Return Controller instance from a controller name
63+
* @param string $controllerName
64+
* @return object
65+
* @throws \Exception
66+
*/
67+
private function getControllerFromName(string $controllerName)
68+
{
69+
$controller = $this->projectNamespace . $this->controllerPackage . '\\' . ucfirst($controllerName);
70+
if (!class_exists($controller)) {
71+
throw new \Exception('controller ' . $controllerName . ' not found');
72+
}
73+
return new $controller;
3874
}
3975

4076
/**
4177
* Return HTTP Method for request
4278
* @return string
4379
*/
44-
private function getVerbFromRequest()
80+
private function getVerbFromRequest(): string
4581
{
4682
return isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'get';
4783
}
@@ -50,7 +86,7 @@ private function getVerbFromRequest()
5086
* Returns Request uri without query string
5187
* @return string
5288
*/
53-
private function getQuery() : string
89+
private function getQuery(): string
5490
{
5591
$requestUri = $_SERVER['REQUEST_URI'];
5692
$appendUri = strpos($requestUri, '?');
@@ -61,7 +97,7 @@ private function getQuery() : string
6197
* Determine controller and action from Request Uri
6298
* @return array
6399
*/
64-
private function getControllerAndAction() : array
100+
private function getControllerAndAction(): array
65101
{
66102
$parts = explode('/', preg_replace('~^' . Basepath::get() . '~', '', $this->getQuery()));
67103
$action = count($parts) >= 2 ? array_pop($parts) : 'index';
@@ -74,7 +110,7 @@ private function getControllerAndAction() : array
74110
* @param string $namespace
75111
* @return Framework
76112
*/
77-
public function setNamespace(string $namespace = '\Project') : Framework
113+
public function setNamespace(string $namespace = '\Project'): Framework
78114
{
79115
$this->projectNamespace = strlen($namespace) && $namespace{0} != '\\' ? '\\' . $namespace : $namespace;
80116
return $this;
@@ -85,7 +121,7 @@ public function setNamespace(string $namespace = '\Project') : Framework
85121
* @param string $controllerPackage
86122
* @return Framework
87123
*/
88-
public function setControllerPackage(string $controllerPackage = '\Controller') : Framework
124+
public function setControllerPackage(string $controllerPackage = '\Controller'): Framework
89125
{
90126
$this->controllerPackage = strlen($controllerPackage) && $controllerPackage{0} != '\\'
91127
? '\\' . $controllerPackage
@@ -98,9 +134,20 @@ public function setControllerPackage(string $controllerPackage = '\Controller')
98134
* @param string $suffix
99135
* @return Framework
100136
*/
101-
public function setControllerActionSuffix(string $suffix = 'Action') : Framework
137+
public function setControllerActionSuffix(string $suffix = 'Action'): Framework
102138
{
103139
$this->controllerActionSuffix = (string)$suffix;
104140
return $this;
105141
}
142+
143+
/**
144+
* Tells if we should use parameter matching for controllers
145+
* @param bool $active
146+
* @return Framework
147+
*/
148+
public function setParameterMatching($active = true): Framework
149+
{
150+
$this->withParameterMatching = (bool)$active;
151+
return $this;
152+
}
106153
}

tests/FrameworkTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public function postActionWithNoSuffix()
5252
{
5353
echo "Working6";
5454
}
55+
56+
public function postActionWithParameterMatching($i = "a", $n = "b", $u = "c")
57+
{
58+
echo "Working with $u $n $i";
59+
}
5560
}
5661
}
5762

@@ -162,5 +167,38 @@ public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePat
162167
->setControllerActionSuffix('')
163168
->dispatch();
164169
}
170+
171+
public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePathWithPostAndNoParameterMatching()
172+
{
173+
$_SERVER['REQUEST_URI'] = '/recursive/recursive/actionwithparametermatching';
174+
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
175+
$_SERVER['REQUEST_METHOD'] = 'POST';
176+
$this->expectOutputString("Working with c b a");
177+
$nano = new \Nano\Framework();
178+
$nano->setNamespace('\OtherNamespace')
179+
->setControllerPackage('')
180+
->setControllerActionSuffix('')
181+
->setParameterMatching()
182+
->dispatch();
183+
}
184+
185+
public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePathWithPostAndParameterMatching()
186+
{
187+
$_SERVER['REQUEST_URI'] = '/recursive/recursive/actionwithparametermatching';
188+
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
189+
$_SERVER['REQUEST_METHOD'] = 'POST';
190+
$_REQUEST = [
191+
'u' => 'You',
192+
'i' => 'Me',
193+
'n' => 'and',
194+
];
195+
$this->expectOutputString("Working with You and Me");
196+
$nano = new \Nano\Framework();
197+
$nano->setNamespace('\OtherNamespace')
198+
->setControllerPackage('')
199+
->setControllerActionSuffix('')
200+
->setParameterMatching()
201+
->dispatch();
202+
}
165203
}
166204
}

0 commit comments

Comments
 (0)