Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/vendor
.DS_Store
composer.lock
/.php_cs.cache
/.phpunit.result.cache
/composer.lock
/vendor/
25 changes: 25 additions & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests');

return PhpCsFixer\Config::create()
->setRules([
'@PSR2' => true,
'@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_line_before_statement' => false,
'concat_space' => ['spacing' => 'one'],
'function_declaration' => ['closure_function_spacing' => 'none'],
'increment_style' => false,
'phpdoc_align' => ['align' => 'left'],
'phpdoc_separation' => false,
'phpdoc_summary' => false,
'phpdoc_to_comment' => false,
'yoda_style' => false,
])
->setFinder($finder);

// __END__
// vim: filetype=php
10 changes: 6 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
language: php

php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4

cache:
directories:
Expand All @@ -16,9 +16,11 @@ install:

script:
- mkdir -p build/logs
- php ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
- ./vendor/bin/psalm --no-progress
- ./vendor/bin/php-cs-fixer fix -v --dry-run --stop-on-violation --using-cache=no
- ./vendor/bin/phpunit --verbose --coverage-clover build/logs/clover.xml

after_script:
- travis_retry php ./vendor/bin/coveralls
- travis_retry php ./vendor/bin/php-coveralls

sudo: false
2 changes: 2 additions & 0 deletions benchmarks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor/
13 changes: 13 additions & 0 deletions benchmarks/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"require": {
"nikic/fast-route": "^1.0",
"php": ">=7.1",
"phpbench/phpbench": "^0.17"
},
"autoload": {
"psr-4": {
"Emonkak\\Router\\": "../src/",
"Emonkak\\Router\\Benchmarks\\": "src/"
}
}
}
3 changes: 3 additions & 0 deletions benchmarks/phpbench.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"bootstrap": "vendor/autoload.php"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router\Benchmarks;

use Emonkak\Router\RouterInterface;
Expand Down Expand Up @@ -51,20 +53,20 @@ public function benchNotMatch()

protected function buildRouter()
{
return $this->prepareRouter()
->route('/', 0)
->route('/foo/', 1)
->route('/bar/', 2)
->route('/baz/', 3)
->route('/foo/:first', 4)
->route('/bar/:first', 5)
->route('/baz/:first', 6)
->route('/foo/:first/qux', 7)
->route('/bar/:first/quux', 8)
->route('/baz/:first/foobar', 9)
->route('/foo/:first/qux/:second', 10)
->route('/bar/:first/quux/:second', 11)
->route('/baz/:first/foobar/:second', 12);
$router = $this->prepareRouter();
$router->addroute('/', 0);
$router->addroute('/foo/', 1);
$router->addroute('/bar/', 2);
$router->addroute('/baz/', 3);
$router->addroute('/foo/:first', 4);
$router->addroute('/bar/:first', 5);
$router->addroute('/baz/:first', 6);
$router->addroute('/foo/:first/qux', 7);
$router->addroute('/bar/:first/quux', 8);
$router->addroute('/baz/:first/foobar', 9);
$router->addroute('/foo/:first/qux/:second', 10);
$router->addroute('/bar/:first/quux/:second', 11);
$router->addroute('/baz/:first/foobar/:second', 12);
}

abstract protected function prepareRouter();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router\Benchmarks;

use FastRoute\Dispatcher;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router\Benchmarks;

use Emonkak\Router\RegexpRouter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router\Benchmarks;

use Emonkak\Router\TrieRouter;
Expand Down
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
}
],
"require": {
"php": ">=5.6"
"php": ">=7.1"
},
"require-dev": {
"nikic/fast-route": "^1.0",
"phpbench/phpbench": "^0.10.0",
"phpunit/phpunit": "^5.7",
"satooshi/php-coveralls": "^1.0"
"phpunit/phpunit": "^7.0",
"php-coveralls/php-coveralls": "^2.0",
"vimeo/psalm": "^3.11",
"friendsofphp/php-cs-fixer": "^2.16"
},
"autoload": {
"psr-4": {
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite>
<testsuite name="tests">
<directory>./tests/</directory>
</testsuite>
</testsuites>
Expand Down
13 changes: 13 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<psalm
totallyTyped="true"
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
</projectFiles>
</psalm>
73 changes: 36 additions & 37 deletions src/AbstractRouterBuilder.php
Original file line number Diff line number Diff line change
@@ -1,97 +1,96 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router;

/**
* @template THandler
* @template TParam
*/
abstract class AbstractRouterBuilder
{
/**
* @var array
* @var array<string,array<string,THandler>>
*/
protected $routes = [];

/**
* @param string $method
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function route($method, $path, $handler)
public function get(string $path, $handler): self
{
if (!isset($this->routes[$path])) {
$this->routes[$path] = [];
}

$this->routes[$path][$method] = $handler;

return $this;
return $this->route('GET', $path, $handler);
}

/**
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function get($path, $handler)
public function post(string $path, $handler): self
{
return $this->route('GET', $path, $handler);
return $this->route('POST', $path, $handler);
}

/**
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function post($path, $handler)
public function delete(string $path, $handler): self
{
return $this->route('POST', $path, $handler);
return $this->route('DELETE', $path, $handler);
}

/**
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function delete($path, $handler)
public function put(string $path, $handler): self
{
return $this->route('DELETE', $path, $handler);
return $this->route('PUT', $path, $handler);
}

/**
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function put($path, $handler)
public function patch(string $path, $handler): self
{
return $this->route('PUT', $path, $handler);
return $this->route('PATCH', $path, $handler);
}

/**
* @param string $path
* @param mixed $handler
* @param THandler $handler
* @return $this
*/
public function patch($path, $handler)
public function route(string $method, string $path, $handler): self
{
return $this->route('PATCH', $path, $handler);
if (!isset($this->routes[$path])) {
$this->routes[$path] = [];
}

$this->routes[$path][$method] = $handler;

return $this;
}

/**
* @return RouterInterface
* @return RouterInterface<THandler,TParam>
*/
public function build()
public function build(): RouterInterface
{
$router = $this->prepareRouter();

foreach ($this->routes as $path => $route) {
$router->route($path, $route);
$router->addRoute($path, $route);
}

return $router;
}

/**
* @return RoutableRouterInterface
* @return RoutableRouterInterface<THandler,TParam>
*/
abstract protected function prepareRouter();
abstract protected function prepareRouter(): RoutableRouterInterface;
}
14 changes: 10 additions & 4 deletions src/CompositeRouter.php
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
<?php

declare(strict_types=1);

namespace Emonkak\Router;

/**
* @template THandler
* @template TParam
*/
class CompositeRouter implements RouterInterface
{
/**
* @var array
* @var RouterInterface<THandler,TParam>[]
*/
private $routers;

/**
* @param array $routers
* @param RouterInterface<THandler,TParam>[] $routers
*/
public function __construct(array $routers)
{
$this->routers = $routers;
}

/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function match($path)
public function match(string $path): ?array
{
foreach ($this->routers as $prefix => $router) {
if (strpos($path, $prefix) === 0) {
Expand Down
Loading