Skip to content

Commit

Permalink
[#1] - add parameter matching in actions (must be activated)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaymoulin committed Jul 24, 2017
1 parent 2cec8a5 commit 59c902d
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 14 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,32 @@ http://mysite.tld/test/action | \Project\Controller\Test::actio
http://mysite.tld/also/work/with/full/path | \Project\Controller\Also\Work\With\Full::pathAction
http://mysite.tld/my/normal | \Project\Controller\My::getNormalAction
http://mysite.tld/my/normal (with HTTP post) | \Project\Controller\My::postNormalAction

## Parameter Matching

Since 0.6.0, you can use *"Parameter Matching"*

Simply activate it when dispatching :

```php
require_once ('vendor/autoload.php');
$nano = new \Nano\Framework();
$nano->setParameterMatching->dispatch();
```

And then you'll be able to use it like this :

```php
<?php
namespace \Project\Controller;

class MyAwesomeController
{
public function getHelloAction($age, $name)
{
echo "Hello $name, I'm {$age}yo"; //please, use this code for test only
}
}
```

and call `http://mysite.tld/myawesomecontroller/hello?name=World&age=900` to display "Hello World, I'm 900yo" !
75 changes: 61 additions & 14 deletions src/Framework.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);

namespace Nano;

Expand All @@ -12,6 +12,7 @@ final class Framework
private $projectNamespace = '\Project';
private $controllerPackage = '\Controller';
private $controllerActionSuffix = 'Action';
private $withParameterMatching = false;

/**
* Dispatch the request
Expand All @@ -21,27 +22,62 @@ final class Framework
public function dispatch()
{
list($controllerName, $action) = $this->getControllerAndAction();
$controller = $this->projectNamespace . $this->controllerPackage . '\\' . ucfirst($controllerName);
if (!class_exists($controller)) {
throw new \Exception('controller ' . $controllerName . ' not found');
};
$controller = new $controller;
$controller = $this->getControllerFromName($controllerName);
$finalAction = $this->getVerbFromRequest() . ucfirst($action) . $this->controllerActionSuffix;
if (is_callable(array($controller, $finalAction))) {
return $controller->$finalAction();
return call_user_func_array(
[$controller, $finalAction],
$this->getParametersForMatching($controller, $finalAction)
);
}
$finalAction = $action . $this->controllerActionSuffix;
if (!is_callable(array($controller, $finalAction))) {
throw new \Exception('action ' . $finalAction . ' not found in controller ' . $controllerName);
}
return $controller->$finalAction();
return call_user_func_array(
[$controller, $finalAction],
$this->getParametersForMatching($controller, $finalAction)
);
}

/**
* Returns parameters from request matching specified controller and action
* @param object $controller
* @param string $action
* @return array
*/
private function getParametersForMatching($controller, string $action): array
{
$parameters = [];
$reflection = new \ReflectionMethod($controller, $action);
foreach ($reflection->getParameters() as $param) {
if (isset($_REQUEST[$param->name])) {
$parameters[$param->name] = $_REQUEST[$param->name];
}
}
return $parameters;
}

/**
* Return Controller instance from a controller name
* @param string $controllerName
* @return object
* @throws \Exception
*/
private function getControllerFromName(string $controllerName)
{
$controller = $this->projectNamespace . $this->controllerPackage . '\\' . ucfirst($controllerName);
if (!class_exists($controller)) {
throw new \Exception('controller ' . $controllerName . ' not found');
}
return new $controller;
}

/**
* Return HTTP Method for request
* @return string
*/
private function getVerbFromRequest()
private function getVerbFromRequest(): string
{
return isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'get';
}
Expand All @@ -50,7 +86,7 @@ private function getVerbFromRequest()
* Returns Request uri without query string
* @return string
*/
private function getQuery() : string
private function getQuery(): string
{
$requestUri = $_SERVER['REQUEST_URI'];
$appendUri = strpos($requestUri, '?');
Expand All @@ -61,7 +97,7 @@ private function getQuery() : string
* Determine controller and action from Request Uri
* @return array
*/
private function getControllerAndAction() : array
private function getControllerAndAction(): array
{
$parts = explode('/', preg_replace('~^' . Basepath::get() . '~', '', $this->getQuery()));
$action = count($parts) >= 2 ? array_pop($parts) : 'index';
Expand All @@ -74,7 +110,7 @@ private function getControllerAndAction() : array
* @param string $namespace
* @return Framework
*/
public function setNamespace(string $namespace = '\Project') : Framework
public function setNamespace(string $namespace = '\Project'): Framework
{
$this->projectNamespace = strlen($namespace) && $namespace{0} != '\\' ? '\\' . $namespace : $namespace;
return $this;
Expand All @@ -85,7 +121,7 @@ public function setNamespace(string $namespace = '\Project') : Framework
* @param string $controllerPackage
* @return Framework
*/
public function setControllerPackage(string $controllerPackage = '\Controller') : Framework
public function setControllerPackage(string $controllerPackage = '\Controller'): Framework
{
$this->controllerPackage = strlen($controllerPackage) && $controllerPackage{0} != '\\'
? '\\' . $controllerPackage
Expand All @@ -98,9 +134,20 @@ public function setControllerPackage(string $controllerPackage = '\Controller')
* @param string $suffix
* @return Framework
*/
public function setControllerActionSuffix(string $suffix = 'Action') : Framework
public function setControllerActionSuffix(string $suffix = 'Action'): Framework
{
$this->controllerActionSuffix = (string)$suffix;
return $this;
}

/**
* Tells if we should use parameter matching for controllers
* @param bool $active
* @return Framework
*/
public function setParameterMatching($active = true): Framework
{
$this->withParameterMatching = (bool)$active;
return $this;
}
}
38 changes: 38 additions & 0 deletions tests/FrameworkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public function postActionWithNoSuffix()
{
echo "Working6";
}

public function postActionWithParameterMatching($i = "a", $n = "b", $u = "c")
{
echo "Working with $u $n $i";
}
}
}

Expand Down Expand Up @@ -162,5 +167,38 @@ public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePat
->setControllerActionSuffix('')
->dispatch();
}

public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePathWithPostAndNoParameterMatching()
{
$_SERVER['REQUEST_URI'] = '/recursive/recursive/actionwithparametermatching';
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->expectOutputString("Working with c b a");
$nano = new \Nano\Framework();
$nano->setNamespace('\OtherNamespace')
->setControllerPackage('')
->setControllerActionSuffix('')
->setParameterMatching()
->dispatch();
}

public function testDispatchSuccessWhenOtherSubPackageAndNoSuffixAndRecursivePathWithPostAndParameterMatching()
{
$_SERVER['REQUEST_URI'] = '/recursive/recursive/actionwithparametermatching';
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_REQUEST = [
'u' => 'You',
'i' => 'Me',
'n' => 'and',
];
$this->expectOutputString("Working with You and Me");
$nano = new \Nano\Framework();
$nano->setNamespace('\OtherNamespace')
->setControllerPackage('')
->setControllerActionSuffix('')
->setParameterMatching()
->dispatch();
}
}
}

0 comments on commit 59c902d

Please sign in to comment.