Skip to content

Commit 071c6c8

Browse files
author
Fady Michel
committedMar 5, 2021
add middleware and improvement router
1 parent 30beb8f commit 071c6c8

File tree

6 files changed

+332
-10
lines changed

6 files changed

+332
-10
lines changed
 

‎composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
],
1818
"require": {
1919
"php": ">=7.3",
20-
"psr/http-message": "~1.0"
20+
"psr/http-message": "^1.0",
21+
"psr/http-server-middleware": "^1.0",
22+
"psr/http-factory": "^1.0"
2123
},
2224
"require-dev": {
2325
"phpunit/phpunit": "~7.1"

‎composer.lock

+161-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎index.php

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
use LiteApp\Middleware\ControllerMiddleware;
4+
5+
require 'vendor/autoload.php';
6+
error_reporting(E_ALL);
7+
ini_set("display_errors", 1);
8+
9+
10+
class HomeController
11+
{
12+
13+
public function __invoke()
14+
{
15+
return '<p>Hello world</p>';
16+
}
17+
}
18+
19+
class ArticleController
20+
{
21+
22+
public function list()
23+
{
24+
return '<ul>
25+
<li>Article 1</li>
26+
<li>Article 2</li>
27+
</ul>';
28+
}
29+
30+
public function view(int $id)
31+
{
32+
return "<p>Article $id</p>";
33+
}
34+
}
35+
36+
37+
//$router = new \DevCoder\Router([
38+
// new \DevCoder\Route('home_page', '/', function () {
39+
// return '<p>Hello world</p>';
40+
// })
41+
//]);
42+
43+
$router = new \DevCoder\Router([
44+
new \DevCoder\Route('home_page', '/', function () {
45+
return '<p>Hello world</p>';
46+
}),
47+
// new \DevCoder\Route('home_page', '/', [HomeController::class]),
48+
new \DevCoder\Route('articles', '/articles', [ArticleController::class, 'list']),
49+
new \DevCoder\Route('article_view', '/articles/{id}', [ArticleController::class, 'view'])
50+
]);
51+
52+
try {
53+
54+
$route = $router->matchFromPath('/articles/1', 'GET');
55+
56+
$callback = $route->getCallback();
57+
$arguments = $route->getVars();
58+
59+
//
60+
if (is_array($callback)) {
61+
62+
$controller = new $callback[0]();
63+
if (is_callable($controller)) {
64+
$callback = $controller;
65+
}else {
66+
$action = $callback[1] ?? null;
67+
if (!method_exists($controller, $action)) {
68+
69+
if ($action === null) {
70+
throw new \BadMethodCallException(sprintf('Please use a Method on class %s.', get_class($controller)));
71+
}
72+
throw new \BadMethodCallException(sprintf('Method "%s" on class %s does not exist.', $action, get_class($controller)));
73+
}
74+
75+
$callback = [$controller, $action];
76+
}
77+
78+
}
79+
80+
echo $callback(...array_values($arguments));
81+
82+
} catch (\BadMethodCallException $e) {
83+
throw $e;
84+
} catch (\Exception $e) {
85+
header("HTTP/1.0 404 Not Found");
86+
}
87+
88+

‎src/Route.php

+16-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class Route
2121
/**
2222
* @var array<string>
2323
*/
24-
protected $controller = [];
24+
protected $parameters = [];
2525

2626
/**
2727
* @var array<string>
@@ -33,14 +33,25 @@ class Route
3333
*/
3434
protected $vars = [];
3535

36-
public function __construct(string $name, string $path, array $controller, array $methods = ['GET', 'POST'])
36+
/**
37+
* Route constructor.
38+
* @param string $name
39+
* @param string $path
40+
* @param array $parameters
41+
* $parameters = [
42+
* 0 => (string) Controller name : HomeController::class.
43+
* 1 => (string|null) Method name or null if invoke method
44+
* ]
45+
* @param array $methods
46+
*/
47+
public function __construct(string $name, string $path, array $parameters, array $methods = ['GET', 'POST'])
3748
{
3849
if ($methods === []) {
3950
throw new \InvalidArgumentException('HTTP methods argument was empty; must contain at least one method');
4051
}
4152
$this->name = $name;
4253
$this->path = $path;
43-
$this->controller = $controller;
54+
$this->parameters = $parameters;
4455
$this->methods = $methods;
4556
}
4657

@@ -74,9 +85,9 @@ public function getPath(): string
7485
return $this->path;
7586
}
7687

77-
public function getController(): array
88+
public function getParameters(): array
7889
{
79-
return $this->controller;
90+
return $this->parameters;
8091
}
8192

8293
public function getMethods(): array

‎src/RouterMiddleware.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace DevCoder;
4+
5+
use Exception;
6+
use Psr\Http\Message\ResponseFactoryInterface;
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\MiddlewareInterface;
10+
use Psr\Http\Server\RequestHandlerInterface;
11+
12+
/**
13+
* Class RouterMiddleware
14+
* @package App\Middleware
15+
*/
16+
final class RouterMiddleware implements MiddlewareInterface
17+
{
18+
const CONTROLLER = '_controller';
19+
const ACTION = '_action';
20+
const NAME = '_name';
21+
22+
/**
23+
* @var RouterInterface
24+
*/
25+
private $router;
26+
/**
27+
* @var ResponseFactoryInterface
28+
*/
29+
private $responseFactory;
30+
31+
/**
32+
* RouterMiddleware constructor.
33+
* @param RouterInterface $router
34+
* @param ResponseFactoryInterface $responseFactory
35+
*/
36+
public function __construct(RouterInterface $router, ResponseFactoryInterface $responseFactory)
37+
{
38+
$this->router = $router;
39+
$this->responseFactory = $responseFactory;
40+
}
41+
42+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
43+
{
44+
try {
45+
$route = $this->router->match($request);
46+
$controller = $route->getParameters();
47+
$attributes = array_merge([
48+
static::CONTROLLER => $controller[0],
49+
static::ACTION => $controller[1] ?? null,
50+
static::NAME => $route->getName(),
51+
], $route->getVars());
52+
53+
foreach ($attributes as $key => $value) {
54+
$request = $request->withAttribute($key, $value);
55+
}
56+
57+
} catch (Exception $exception) {
58+
return $this->responseFactory->createResponse(404);
59+
}
60+
61+
return $handler->handle($request);
62+
}
63+
}

‎tests/RouterTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function testMatchRoute() {
3838
$route = $this->router->matchFromPath('/view/article/25', 'GET');
3939
$this->assertInstanceOf(Route::class, $route);
4040

41-
$this->assertNotEmpty($route->getController());
41+
$this->assertNotEmpty($route->getParameters());
4242
$this->assertNotEmpty($route->getMethods());
4343
$this->assertSame(['id' => '25'], $route->getVars());
4444

0 commit comments

Comments
 (0)
Please sign in to comment.