Merge pull request #498 from skipperbent/v4-array-callback

[FEATURE] Added support for class hinting on routes as requested by #491
This commit is contained in:
Simon Sessingø
2021-03-21 07:55:27 +01:00
committed by GitHub
9 changed files with 69 additions and 35 deletions

12
.idea/workspace.xml generated
View File

@@ -6,7 +6,14 @@
<component name="ChangeListManager">
<list default="true" id="a7058529-bdc4-40b4-a50d-c50564dc83f0" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/Http/Input/InputItem.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/IRoute.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/IRoute.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/Route.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteController.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteController.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteResource.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/Route/RouteResource.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/Pecee/SimpleRouter/SimpleRouter.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Pecee/SimpleRouter/SimpleRouter.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterRouteTest.php" beforeDir="false" afterPath="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterRouteTest.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterUrlTest.php" beforeDir="false" afterPath="$PROJECT_DIR$/tests/Pecee/SimpleRouter/RouterUrlTest.php" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -426,6 +433,8 @@
<workItem from="1616030812009" duration="3745000" />
<workItem from="1616076234772" duration="377000" />
<workItem from="1616086876180" duration="6839000" />
<workItem from="1616147368571" duration="141000" />
<workItem from="1616286180427" duration="3108000" />
</task>
<servers />
</component>
@@ -525,6 +534,7 @@
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="XSLT-Support.FileAssociations.UIState">
<expand />

View File

@@ -33,6 +33,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c
- [Helper functions](#helper-functions)
- [Routes](#routes)
- [Basic routing](#basic-routing)
- [Class hinting](#class-hinting)
- [Available methods](#available-methods)
- [Multiple HTTP-verbs](#multiple-http-verbs)
- [Route parameters](#route-parameters)
@@ -404,6 +405,14 @@ SimpleRouter::get('/', function() {
});
```
### Class hinting
You can use class hinting to load a class & method like this:
```php
SimpleRouter::get('/', [MyClass::class, 'myMethod']);
```
### Available methods
Here you can see a list over all available routes:
@@ -785,12 +794,17 @@ SimpleRouter::group(['middleware' => \Demo\Middlewares\Site::class, 'exceptionHa
SimpleRouter::get('/answers/{id}', 'ControllerAnswers@show', ['where' => ['id' => '[0-9]+']]);
/**
* Class hinting is supported too
*/
SimpleRouter::get('/answers/{id}', [ControllerAnswers::class, 'show'], ['where' => ['id' => '[0-9]+']]);
/**
* Restful resource (see IRestController interface for available methods)
*/
SimpleRouter::resource('/rest', ControllerRessource::class);
SimpleRouter::resource('/rest', ControllerResource::class);
/**
@@ -811,7 +825,6 @@ SimpleRouter::group(['middleware' => \Demo\Middlewares\Site::class, 'exceptionHa
});
SimpleRouter::get('/page/404', 'ControllerPage@notFound', ['as' => 'page.notfound']);
```
---

View File

@@ -82,7 +82,7 @@ interface IRoute
/**
* Set callback
*
* @param string $callback
* @param string|array|\Closure $callback
* @return static
*/
public function setCallback($callback): self;

View File

@@ -95,26 +95,22 @@ abstract class Route implements IRoute
$router->debug('Executing callback');
/* When the callback is a function */
return $router->getClassLoader()->loadClosure($callback, $parameters);
}
/* When the callback is a class + method */
$controller = explode('@', $callback);
$controller = $this->getClass();
$method = $this->getMethod();
$namespace = $this->getNamespace();
$className = ($namespace !== null && $controller[0][0] !== '\\') ? $namespace . '\\' . $controller[0] : $controller[0];
$className = ($namespace !== null && $controller[0] !== '\\') ? $namespace . '\\' . $controller : $controller;
$router->debug('Loading class %s', $className);
$class = $router->getClassLoader()->loadClass($className);
if (\count($controller) === 1) {
if ($method === null) {
$controller[1] = '__invoke';
}
$method = $controller[1];
if (method_exists($class, $method) === false) {
throw new NotFoundHttpException(sprintf('Method "%s" does not exist in class "%s"', $method, $className), 404);
}
@@ -271,7 +267,7 @@ abstract class Route implements IRoute
/**
* Set callback
*
* @param string $callback
* @param string|array\Closure $callback
* @return static
*/
public function setCallback($callback): IRoute
@@ -291,6 +287,10 @@ abstract class Route implements IRoute
public function getMethod(): ?string
{
if(\is_array($this->callback) === true && \count($this->callback) > 1) {
return $this->callback[1];
}
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback);
@@ -302,9 +302,12 @@ abstract class Route implements IRoute
public function getClass(): ?string
{
if(\is_array($this->callback) === true && \count($this->callback) > 0) {
return $this->callback[0];
}
if (\is_string($this->callback) === true && strpos($this->callback, '@') !== false) {
$tmp = explode('@', $this->callback);
return $tmp[0];
}
@@ -313,15 +316,13 @@ abstract class Route implements IRoute
public function setMethod(string $method): IRoute
{
$this->callback = sprintf('%s@%s', $this->getClass(), $method);
$this->callback = [$this->getClass(), $method];
return $this;
}
public function setClass(string $class): IRoute
{
$this->callback = sprintf('%s@%s', $class, $this->getMethod());
$this->callback = [$class, $this->getMethod()];
return $this;
}

View File

@@ -110,7 +110,7 @@ class RouteController extends LoadableRoute implements IControllerRoute
$this->parameters = \array_slice($path, 1);
// Set callback
$this->setCallback($this->controller . '@' . $this->method);
$this->setCallback([$this->controller, $this->method]);
return true;
}

View File

@@ -78,7 +78,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
protected function call($method): bool
{
$this->setCallback($this->controller . '@' . $method);
$this->setCallback([$this->controller, $method]);
return true;
}

View File

@@ -12,7 +12,6 @@ namespace Pecee\SimpleRouter;
use DI\Container;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Http\Exceptions\MalformedUrlException;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request;
use Pecee\Http\Response;
@@ -178,7 +177,7 @@ class SimpleRouter
* Route the given url to your callback on GET request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
*
* @return RouteUrl
@@ -192,7 +191,7 @@ class SimpleRouter
* Route the given url to your callback on POST request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl
*/
@@ -205,7 +204,7 @@ class SimpleRouter
* Route the given url to your callback on PUT request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl
*/
@@ -218,7 +217,7 @@ class SimpleRouter
* Route the given url to your callback on PATCH request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl
*/
@@ -231,7 +230,7 @@ class SimpleRouter
* Route the given url to your callback on OPTIONS request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl
*/
@@ -244,7 +243,7 @@ class SimpleRouter
* Route the given url to your callback on DELETE request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl
*/
@@ -307,7 +306,7 @@ class SimpleRouter
* Alias for the form method
*
* @param string $url
* @param callable $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
@@ -322,7 +321,7 @@ class SimpleRouter
* Route the given url to your callback on POST and GET request method.
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
@@ -337,7 +336,7 @@ class SimpleRouter
*
* @param array $requestMethods
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
*/
@@ -358,7 +357,7 @@ class SimpleRouter
* This type will route the given url to your callback and allow any type of request method
*
* @param string $url
* @param string|\Closure $callback
* @param string|array|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
*/
@@ -382,7 +381,7 @@ class SimpleRouter
* @param array|null $settings
* @return RouteController|IRoute
*/
public static function controller(string $url, $controller, array $settings = null)
public static function controller(string $url, string $controller, array $settings = null)
{
$route = new RouteController($url, $controller);
$route = static::addDefaultNamespace($route);
@@ -402,7 +401,7 @@ class SimpleRouter
* @param array|null $settings
* @return RouteResource|IRoute
*/
public static function resource(string $url, $controller, array $settings = null)
public static function resource(string $url, string $controller, array $settings = null)
{
$route = new RouteResource($url, $controller);
$route = static::addDefaultNamespace($route);

View File

@@ -199,4 +199,15 @@ class RouterRouteTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('custom-regex', $output);
}
public function testClassHint()
{
TestRouter::get('/my/test/url', ['DummyController', 'method1']);
TestRouter::all('/my/test/url', ['DummyController', 'method1']);
TestRouter::match(['put', 'get', 'post'], '/my/test/url', ['DummyController', 'method1']);
TestRouter::debug('/my/test/url', 'get');
$this->assertTrue(true);
}
}

View File

@@ -78,8 +78,8 @@ class RouterUrlTest extends \PHPUnit\Framework\TestCase
public function testSimilarUrls()
{
// Match normal route on alias
TestRouter::resource('/url11', 'DummyController@method1');
TestRouter::resource('/url1', 'DummyController@method1', ['as' => 'match']);
TestRouter::get('/url11', 'DummyController@method1');
TestRouter::resource('/url1', 'ResourceController', ['as' => 'match']);
TestRouter::debugNoReset('/url1', 'get');