Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4aeaf91

Browse files
assign Expr To Parameters
1 parent 94301ce commit 4aeaf91

File tree

6 files changed

+103
-52
lines changed

6 files changed

+103
-52
lines changed

‎src/Helper.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace DevCoder;
44

5-
class Helper
5+
finalclass Helper
66
{
77
public static function trimPath(string $path): string
88
{

‎src/Route.php‎

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ final class Route
3838
/**
3939
* @var array<string>
4040
*/
41-
private $attributes = [];
41+
private array $attributes = [];
42+
43+
/**
44+
* @var array<string, string>
45+
*/
46+
private array $wheres = [];
4247

4348
/**
4449
* Route constructor.
@@ -51,7 +56,7 @@ final class Route
5156
* ]
5257
* @param array $methods
5358
*/
54-
public function __construct(string $name, string $path, $handler, array $methods = ['GET'])
59+
public function __construct(string $name, string $path, $handler, array $methods = ['GET', 'HEAD'])
5560
{
5661
if ($methods === []) {
5762
throw new InvalidArgumentException('HTTP methods argument was empty; must contain at least one method');
@@ -60,6 +65,10 @@ public function __construct(string $name, string $path, $handler, array $methods
6065
$this->path = Helper::trimPath($path);
6166
$this->handler = $handler;
6267
$this->methods = $methods;
68+
69+
if (in_array('GET', $this->methods) && !in_array('HEAD', $this->methods)) {
70+
$this->methods[] = 'HEAD';
71+
}
6372
}
6473

6574
public function match(string $path): bool
@@ -70,16 +79,22 @@ public function match(string $path): bool
7079
$regex = str_replace($variable, '(?P<' . $varName . '>[^/]++)', $regex);
7180
}
7281

73-
if (preg_match('#^' . $regex . '$#sD', Helper::trimPath($path), $matches)) {
74-
$values = array_filter($matches, static function ($key) {
75-
return is_string($key);
76-
}, ARRAY_FILTER_USE_KEY);
77-
foreach ($values as $key => $value) {
78-
$this->attributes[$key] = $value;
82+
if (!preg_match('#^' . $regex . '$#sD', Helper::trimPath($path), $matches)) {
83+
return false;
84+
}
85+
86+
$values = array_filter($matches, static function ($key) {
87+
return is_string($key);
88+
}, ARRAY_FILTER_USE_KEY);
89+
90+
foreach ($values as $key => $value) {
91+
if (array_key_exists($key, $this->wheres) && !preg_match('/^'.$this->wheres[$key].'$/', $value)) {
92+
return false;
7993
}
80-
returntrue;
94+
$this->attributes[$key] = $value;
8195
}
82-
return false;
96+
97+
return true;
8398
}
8499

85100
public function getName(): string
@@ -120,4 +135,41 @@ public function getAttributes(): array
120135
{
121136
return $this->attributes;
122137
}
138+
139+
public function whereNumber(...$parameters): self
140+
{
141+
$this->assignExprToParameters($parameters, '[0-9]+');
142+
return $this;
143+
}
144+
145+
public function whereSlug(...$parameters): self
146+
{
147+
$this->assignExprToParameters($parameters, '[a-z0-9-]+');
148+
return $this;
149+
}
150+
151+
public function whereAlphaNumeric(...$parameters): self
152+
{
153+
$this->assignExprToParameters($parameters, '[a-zA-Z0-9]+');
154+
return $this;
155+
}
156+
157+
public function whereAlpha(...$parameters): self
158+
{
159+
$this->assignExprToParameters($parameters, '[a-zA-Z]+');
160+
return $this;
161+
}
162+
163+
public function where(string $parameter, string $expression): self
164+
{
165+
$this->wheres[$parameter] = $expression;
166+
return $this;
167+
}
168+
169+
private function assignExprToParameters(array $parameters, string $expression): void
170+
{
171+
foreach ($parameters as $parameter) {
172+
$this->where($parameter, $expression);
173+
}
174+
}
123175
}

‎src/RouterInterface.php‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace DevCoder;
66

7+
use DevCoder\Exception\MethodNotAllowed;
78
use DevCoder\Exception\RouteNotFound;
89
use Psr\Http\Message\ServerRequestInterface;
910

@@ -13,6 +14,7 @@ interface RouterInterface
1314
* @param ServerRequestInterface $serverRequest
1415
* @return Route
1516
* @throws RouteNotFound if no found route.
17+
* @throws MethodNotAllowed if method not allowed.
1618
*/
1719
public function match(ServerRequestInterface $serverRequest): Route;
1820

@@ -21,6 +23,7 @@ public function match(ServerRequestInterface $serverRequest): Route;
2123
* @param string $method
2224
* @return Route
2325
* @throws RouteNotFound if no found route.
26+
* @throws MethodNotAllowed if method not allowed.
2427
*/
2528
public function matchFromPath(string $path, string $method): Route;
2629

‎src/RouterMiddleware.php‎

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,47 +11,35 @@
1111
use Psr\Http\Message\ServerRequestInterface;
1212
use Psr\Http\Server\MiddlewareInterface;
1313
use Psr\Http\Server\RequestHandlerInterface;
14-
use Throwable;
1514

1615
final class RouterMiddleware implements MiddlewareInterface
1716
{
18-
public const CONTROLLER = '_controller';
19-
public const ACTION = '_action';
20-
public const NAME = '_name';
17+
public const ATTRIBUTE_KEY = '__route';
2118

2219
private RouterInterface $router;
2320
private ResponseFactoryInterface $responseFactory;
2421

2522
public function __construct(
2623
RouterInterface $router,
27-
ResponseFactoryInterface $responseFactory)
24+
ResponseFactoryInterface $responseFactory
25+
)
2826
{
2927
$this->router = $router;
3028
$this->responseFactory = $responseFactory;
3129
}
3230

3331
public function process(
3432
ServerRequestInterface $request,
35-
RequestHandlerInterface $handler): ResponseInterface
33+
RequestHandlerInterface $handler
34+
): ResponseInterface
3635
{
3736
try {
3837
$route = $this->router->match($request);
39-
$routeHandler = $route->getHandler();
40-
$attributes = \array_merge([
41-
self::CONTROLLER => $routeHandler[0],
42-
self::ACTION => $routeHandler[1] ?? null,
43-
self::NAME => $route->getName(),
44-
], $route->getAttributes());
45-
46-
foreach ($attributes as $key => $value) {
47-
$request = $request->withAttribute($key, $value);
48-
}
38+
$request = $request->withAttribute(self::ATTRIBUTE_KEY, $route);
4939
} catch (MethodNotAllowed $exception) {
5040
return $this->responseFactory->createResponse(405);
5141
} catch (RouteNotFound $exception) {
5242
return $this->responseFactory->createResponse(404);
53-
} catch (Throwable $exception) {
54-
throw $exception;
5543
}
5644
return $handler->handle($request);
5745
}

‎tests/RouteTest.php‎

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,18 @@
22

33
namespace Test\DevCoder;
44

5-
6-
7-
use DevCoder\Exception\RouteNotFound;
85
use PHPUnit\Framework\TestCase;
96
use DevCoder\Route;
107

11-
/**
12-
* Class RouterTest
13-
* @package Test\Webbym\Routing
14-
*/
158
class RouteTest extends TestCase {
169

1710
public function testNotMatchRoute()
1811
{
1912
$routeWithoutAttribute = new Route('view_articles','/view/article/', ['App\\Controller\\HomeController', 'home']);
2013
$routeWithAttribute = new Route('view_article','/view/article/{article}', ['App\\Controller\\HomeController', 'home']);
2114

22-
$this->assertFalse($routeWithoutAttribute->match('/view/article/1', 'GET'));
23-
$this->assertFalse($routeWithoutAttribute->match('/view/article/1', 'PUT'));
24-
$this->assertFalse($routeWithAttribute->match('/view/article/', 'POST'));
15+
$this->assertFalse($routeWithoutAttribute->match('/view/article/1'));
16+
$this->assertFalse($routeWithAttribute->match('/view/article/'));
2517
}
2618

2719
public function testMatchRoute()
@@ -40,4 +32,29 @@ public function testException()
4032
$this->expectException(\InvalidArgumentException::class);
4133
new Route('view_articles','/view', ['App\\Controller\\HomeController', 'home'], []);
4234
}
35+
36+
public function testWheres()
37+
{
38+
$routes = [
39+
Route::get('blog.show', '/blog/{id}', function () {})->whereNumber('id'),
40+
Route::get('blog.show', '/blog/{slug}', function () {})->whereSlug('slug'),
41+
Route::get('blog.show', '/blog/{slug}/{id}', function () {})
42+
->whereNumber('id')
43+
->whereSlug('slug'),
44+
Route::get('invoice.show', '/invoice/{number}', function () {})->whereAlphaNumeric('number'),
45+
Route::get('invoice.show', '/invoice/{number}', function () {})->whereAlpha('number'),
46+
];
47+
$this->assertTrue($routes[0]->match('/blog/1'));
48+
$this->assertFalse($routes[0]->match('/blog/F1'));
49+
50+
$this->assertTrue($routes[1]->match('/blog/title-of-article'));
51+
$this->assertFalse($routes[1]->match('/blog/title_of_article'));
52+
53+
$this->assertTrue($routes[2]->match('/blog/title-of-article/12'));
54+
55+
$this->assertTrue($routes[3]->match('/invoice/F0004'));
56+
57+
$this->assertFalse($routes[4]->match('/invoice/F0004'));
58+
$this->assertTrue($routes[4]->match('/invoice/FROUIAUI'));
59+
}
4360
}

‎tests/RouterTest.php‎

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,18 @@
99
use InvalidArgumentException;
1010
use PHPUnit\Framework\TestCase;
1111

12-
/**
13-
* Class RouterTest
14-
* @package Test\Webbym\Routing
15-
*/
1612
class RouterTest extends TestCase
1713
{
1814
private Router $router;
1915

2016
public function __construct($name = null, array $data = [], $dataName = '')
2117
{
2218
parent::__construct($name, $data, $dataName);
23-
$routeHome = new Route('home_page', '/home', ['App\\Controller\\HomeController', 'home']);
24-
$routeArticle = new Route('article_page', '/view/article', ['App\\Controller\\HomeController', 'article']);
25-
$routeArticleWithParam = new Route('article_page_by_id', '/view/article/{id}', ['App\\Controller\\HomeController', 'article']);
26-
$routeArticleWithParams = new Route('article_page_by_id_and_page', '/view/article/{id}/{page}', ['App\\Controller\\HomeController', 'article']);
27-
2819
$this->router = (new Router())
29-
->add($routeHome)
30-
->add($routeArticle)
31-
->add($routeArticleWithParam)
32-
->add($routeArticleWithParams);
20+
->add(newRoute('home_page', '/home', ['App\\Controller\\HomeController', 'home']))
21+
->add(newRoute('article_page', '/view/article', ['App\\Controller\\HomeController', 'article']))
22+
->add(newRoute('article_page_by_id', '/view/article/{id}', ['App\\Controller\\HomeController', 'article']))
23+
->add(newRoute('article_page_by_id_and_page', '/view/article/{id}/{page}', ['App\\Controller\\HomeController', 'article']));
3324
}
3425

3526
public function testMatchRoute()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /