Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
02971c6
Allow to create route instance directly
rustamwin Nov 6, 2023
7848f14
Adjust Group
rustamwin Nov 8, 2023
39f05ff
Simplify route classes & add route builders
rustamwin Nov 9, 2023
626151c
Apply fixes from StyleCI
StyleCIBot Nov 9, 2023
3390ea9
Minor improvements
rustamwin Nov 9, 2023
0b0806d
Merge remote-tracking branch 'origin/new-syntax' into new-syntax
rustamwin Nov 9, 2023
a6b7acd
Improvements
rustamwin Nov 9, 2023
bdaec2c
Merge branch 'master' into new-syntax
rustamwin Nov 9, 2023
33f3003
Apply fixes from StyleCI
StyleCIBot Nov 9, 2023
782bf91
Fix
rustamwin Nov 9, 2023
4530d76
Merge remote-tracking branch 'origin/master' into new-syntax
rustamwin Oct 21, 2025
9c2fa2a
Fix tests
rustamwin Oct 21, 2025
ef3eb15
Fix cs
rustamwin Oct 21, 2025
a9af466
Update dependencies, replace redundant `isArrayList` polyfill with ar…
rustamwin Nov 13, 2025
2bc1672
Apply Rector changes (CI)
rustamwin Nov 13, 2025
f025e9d
Update dev dependencies in composer.json
rustamwin Nov 13, 2025
98c0890
Merge remote-tracking branch 'origin/master' into new-syntax
rustamwin Jan 15, 2026
e8d6831
Merge remote-tracking branch 'origin/master' into new-syntax
rustamwin Apr 15, 2026
f26efb4
Refactor tests and route logic: align types, fix assertions, and impr…
rustamwin Apr 15, 2026
c9bacd1
Apply PHP CS Fixer and Rector changes (CI)
rustamwin Apr 15, 2026
2e737fa
Refactor: optimize middleware handling, improve property initializati…
rustamwin Apr 18, 2026
51fca55
Refactor middleware handling: ensure action is included in enabledMid…
rustamwin Apr 18, 2026
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
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@
"friendsofphp/php-cs-fixer": "^3.89.1",
"maglnet/composer-require-checker": "^4.7.1",
"nyholm/psr7": "^1.8.2",
"phpunit/phpunit": "^10.5.45",
"phpunit/phpunit": "^10.5.58",
"psr/container": "^1.1 || ^2.0.2",
"rector/rector": "^2.0.9",
"rector/rector": "^2.2.7",
"roave/infection-static-analysis-plugin": "^1.35",
"spatie/phpunit-watcher": "^1.24",
"vimeo/psalm": "^5.26.1 || ^6.8.6",
"yiisoft/di": "^1.3",
"yiisoft/dummy-provider": "^1.0.1",
"yiisoft/hydrator": "^1.5",
"yiisoft/test-support": "^3.0.1",
"vimeo/psalm": "^5.26.1 || ^6.13.1",
"yiisoft/di": "^1.4",
"yiisoft/dummy-provider": "^1.1.0",
"yiisoft/hydrator": "^1.6.2",
"yiisoft/test-support": "^3.0.2",
"yiisoft/yii-debug": "dev-master"
},
"autoload": {
Expand Down
168 changes: 168 additions & 0 deletions src/Builder/GroupBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Router\Builder;

use RuntimeException;
use Yiisoft\Router\Group;
use Yiisoft\Router\RoutableInterface;
use Yiisoft\Router\Route;

/**
* GroupBuilder allows you to build group of routes using a flexible syntax.
*/
final class GroupBuilder implements RoutableInterface
{
/**
* @var Group[]|RoutableInterface[]|Route[]
*/
private array $routes = [];

/**
* @var array[]|callable[]|string[]
* @psalm-var list<array|callable|string>
*/
private array $middlewares = [];

private array $disabledMiddlewares = [];

/**
* @var string[]
*/
private array $hosts = [];
private bool $routesAdded = false;
private bool $middlewareAdded = false;

/**
* @var array|callable|string|null Middleware definition for CORS requests.
*/
private $corsMiddleware = null;

private function __construct(
private readonly ?string $prefix = null,
private ?string $namePrefix = null,
) {}

/**
* Create a new group instance.
*
* @param string|null $prefix URL prefix to prepend to all routes of the group.
*/
public static function create(?string $prefix = null, ?string $namePrefix = null): self
{
return new self($prefix, $namePrefix);
}

public function routes(Group|Route|RoutableInterface ...$routes): self
{
if ($this->middlewareAdded) {
throw new RuntimeException('routes() can not be used after prependMiddleware().');
}

$new = clone $this;
$new->routes = $routes;
$new->routesAdded = true;

return $new;
}

/**
* Adds a middleware definition that handles CORS requests.
* If set, routes for {@see Method::OPTIONS} request will be added automatically.
*
* @param array|callable|string|null $middlewareDefinition Middleware definition for CORS requests.
*/
public function withCors(array|callable|string|null $middlewareDefinition): self
{
$group = clone $this;
$group->corsMiddleware = $middlewareDefinition;

return $group;
}

/**
* Appends a handler middleware definition that should be invoked for a matched route.
* First added handler will be executed first.
*/
public function middleware(array|callable|string ...$definition): self
{
if ($this->routesAdded) {
throw new RuntimeException('middleware() can not be used after routes().');
}

$new = clone $this;
array_push(
$new->middlewares,
...array_values($definition),
);

return $new;
}

/**
* Prepends a handler middleware definition that should be invoked for a matched route.
* First added handler will be executed last.
*/
public function prependMiddleware(array|callable|string ...$definition): self
{
$new = clone $this;
array_unshift(
$new->middlewares,
...array_values($definition),
);

$new->middlewareAdded = true;

return $new;
}

public function namePrefix(string $namePrefix): self
{
$new = clone $this;
$new->namePrefix = $namePrefix;
return $new;
}

public function host(string $host): self
{
return $this->hosts($host);
}

public function hosts(string ...$hosts): self
{
$new = clone $this;
$new->hosts = array_values($hosts);

Check warning on line 135 in src/Builder/GroupBuilder.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "UnwrapArrayValues": @@ @@ public function hosts(string ...$hosts): self { $new = clone $this; - $new->hosts = array_values($hosts); + $new->hosts = $hosts; return $new; }

return $new;
}

/**
* Excludes middleware from being invoked when action is handled.
* It is useful to avoid invoking one of the parent group middleware for
* a certain route.
*/
public function disableMiddleware(mixed ...$definition): self
{
$new = clone $this;
array_push(
$new->disabledMiddlewares,
...array_values($definition),
);

return $new;
}

public function toRoute(): Group|Route
{
return new Group(
prefix: $this->prefix,
namePrefix: $this->namePrefix,
routes: $this->routes,
middlewares: $this->middlewares,
hosts: $this->hosts,
disabledMiddlewares: $this->disabledMiddlewares,
corsMiddleware: $this->corsMiddleware,
);
}
}
Loading
Loading