diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index e4222875..310300bc 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -1,46 +1,71 @@
-name: PHPunit
+name: PHPUnit
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
+ workflow_dispatch:
permissions:
contents: read
jobs:
build:
-
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
-
- - name: Validate composer.json and composer.lock
- run: composer validate --strict
-
- - name: Cache Composer packages
- id: composer-cache
- uses: actions/cache@v3
- with:
- path: vendor
- key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
- restore-keys: |
- ${{ runner.os }}-php-
-
- - name: Install dependencies
- run: composer install --prefer-dist --no-progress
-
- # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
- # Docs: https://getcomposer.org/doc/articles/scripts.md
-
- # - name: Run test suite
- # run: composer run-script test
- - name: PHPUnit (graychen)
- # You may pin to the exact commit or the version.
- # uses: Graychen/phpunit-action@026f8104f1a6b5bc646df2d495bc8b34080c3e03
- uses: Graychen/phpunit-action@v1.0.0
- with:
- # Configuration file location
- config: phpunit.xml
+ # Шаг 1: Клонирование репозитория
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ # Шаг 2: Настройка PHP и расширений
+ - name: Set up PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.3'
+ extensions: xdebug
+
+ # Шаг 3: Валидация composer.json и composer.lock
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ # Шаг 4: Кэширование зависимостей Composer
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ # Шаг 5: Установка зависимостей
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ # Шаг 6: Загрузка PHPUnit PHAR
+ - name: Download PHPUnit PHAR
+ run: |
+ wget https://phar.phpunit.de/phpunit.phar
+ chmod +x phpunit.phar
+ mv phpunit.phar /usr/local/bin/phpunit
+
+ # Шаг 7: Проверка версии PHPUnit
+ - name: Check PHPUnit version
+ run: phpunit --version
+
+ # Шаг 8: Запуск тестов с генерацией отчета о покрытии
+ - name: Run PHPUnit tests with coverage
+ run: |
+ mkdir -p build/logs
+ phpunit --configuration phpunit.xml --coverage-clover build/logs/clover.xml --debug
+ env:
+ XDEBUG_MODE: coverage
+
+ # Шаг 9: Отправка данных о покрытии в Coveralls
+ - name: Send coverage to Coveralls
+ uses: coverallsapp/github-action@v2
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ path-to-lcov: build/logs/clover.xml
\ No newline at end of file
diff --git a/README.md b/README.md
index 776130db..0f1120ed 100755
--- a/README.md
+++ b/README.md
@@ -1,60 +1,66 @@
[](https://github.com/Jagepard/Rudra-Router/actions/workflows/php.yml)
-[](https://codeclimate.com/github/Jagepard/Rudra-Router)
+[](https://qlty.sh/gh/Jagepard/projects/Rudra-Router)
[](https://www.codefactor.io/repository/github/jagepard/rudra-router)
+[](https://coveralls.io/github/Jagepard/Rudra-Router?branch=master)
-----
# Rudra-Router
-#### Устанавливаем маршрут callback/:name для http метода GET
-_выполняет лямбда-функцию_
+#### Basic installation / Базовая установка
+```php
+use Rudra\Router\Router;
+use Rudra\Container\Rudra;
+
+$router = new Router(Rudra::run());
+```
+#### Installation for facade use / Установка для использования фасада
+```php
+use Rudra\Container\Facades\Rudra;
+use Rudra\Router\RouterFacade as Router;
+use Rudra\Container\Interfaces\RudraInterface;
+
+Rudra::binding()->set([RudraInterface::class => Rudra::run()]);
+```
+
+#### Setting the route / Устанавливаем маршрут callback/:name
```php
$router->get('callback/:name', function ($name) {
echo "Hello $name!";
});
```
-_Для вызова через Фасад Rudra-Container_
+_with Regex_
```php
-use Rudra\Router\RouterFacade as Router;
-
-Router::get('callback/:name', function ($name) {
+$router->get('callback/:[\d]{1,3}', function ($name) {
echo "Hello $name!";
});
```
-_вызывает MainController::read_
+_To call through the Facade / Для вызова через Фасад_
```php
-$router->get('read/:id', [MainController::class, 'read']);
+Router::get('callback/:name', function ($name) {
+ echo "Hello $name!";
+});
```
-_вызывает MainController::read при помощи добавления аннотаций к MainController_
+_with Regex_
```php
-/**
- * @Routing(url = ''read/:id')
- */
-public function read($id)
+Router::get('callback/:[\d]{1,3}', function ($name) {
+ echo "Hello $name!";
+});
```
-_вызывает MainController::read_ и добавляет middleware с ключами before или after соответственно_
+_call / вызывает MainController::read_
```php
-$router->get('read/page', [MainController::class, 'read'], ['before' => [Middleware::class]);
+$router->get('read/:id', [MainController::class, 'read']);
```
-_в аннотациях_
+_To call through the Facade / Для вызова через Фасад_
```php
-/**
- * @Routing(url = 'read/page')
- * @Middleware(name = 'App\Middleware\Middleware')
- */
-public function read()
+Router::get('read/:id', [MainController::class, 'read']);
```
-_Для сбора аннотаций необходимо передать массив классов в которых есть аннотации в annotationCollector_
+_call MainController::read with middleware_
```php
-$router->annotationCollector([
- \App\Controllers\MainController::class,
- \App\Controllers\SecondController::class,
-]);
+$router->get('read/page', [MainController::class, 'read'], ['before' => [Middleware::class]);
```
+_To call through the Facade / Для вызова через Фасад_
```php
-Router::annotationCollector([
- \App\Controllers\MainController::class,
- \App\Controllers\SecondController::class,
-]);
+Router::get('read/page', [MainController::class, 'read'], ['before' => [Middleware::class]);
```
_С параметрами для middleware_
```php
@@ -63,163 +69,60 @@ $router->get('', [MainController::class, 'read'], [
'after' => [FirstMidddleware::class, [SecondMidddleware::class, ['int' => 456, new \stdClass]]]
]);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = '')
- * @Middleware(name = 'App\Middleware\FirstMidddleware')
- * @Middleware(name = 'App\Middleware\SecondMidddleware', params = {int : '456'})
- * @AfterMiddleware(name = 'App\Middleware\FirstMidddleware')
- * @AfterMiddleware(name = 'App\Middleware\SecondMidddleware', params = {int : '456'})
- */
-public function read()
-```
-_При передаче параметров в middleware необходимо добавлять параметр "array $params"_
-```php
-public function __invoke(array $params, array $middlewares)
-```
-_Если параметры не передаются, то:_
-```php
-public function __invoke(array $middlewares)
-```
-_Следующие вызовы без параметров равны_
-```php
-'before' => [FirstMidddleware::class, SecondMidddleware::class]],
-'before' => [[FirstMidddleware::class], [SecondMidddleware::class]]
-```
-#### Устанавливаем маршрут create/:id для http метода POST
-_вызывает MainController::create_
+_call / вызывает MainController::create_
```php
$router->post('create/:id', [MainController::class, 'create']);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = 'create/:id', method = 'POST')
- */
-public function create($id)
-```
-#### Устанавливаем маршрут update/:id для http метода PUT
-_вызывает MainController::update_
+_call / вызывает MainController::update_
```php
$router->put('update/:id', [MainController::class, 'update']);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = 'update/:id', method = 'PUT')
- */
-public function update($id)
-```
-#### Устанавливаем маршрут update/:id для http метода PATCH
-_вызывает MainController::update_
+_call / вызывает MainController::update_
```php
$router->patch('update/:id', [MainController::class, 'update']);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = 'update/:id', method = 'PATCH')
- */
-public function update($id)
-```
-#### Устанавливаем маршрут delete/:id для http метода DELETE
-_вызывает MainController::delete_
+_call / вызывает MainController::delete_
```php
$router->delete('delete/:id', [MainController::class, 'delete']);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = 'delete/:id', method = 'DELETE')
- */
-public function delete($id)
-```
-#### Устанавливаем маршрут any/:id для http методов GET|POST|PUT|PATCH|DELETE
-_вызывает MainController::any_
+_call / вызывает MainController::any 'GET|POST|PUT|PATCH|DELETE'_
```php
$router->any('any/:id', [MainController::class, 'any']);
```
-_в аннотациях_
-```php
-/**
- * @Routing(url = 'any/:id', method = 'GET|POST|PUT|PATCH|DELETE')
- */
-public function any($id)
-```
-#### Устанавливаем ресурс для маршрута api/:id, методы GET|POST|PUT|DELETE
-_вызывает MainController::read для GET_
+_call / вызывает MainController::read для GET_
-_вызывает MainController::create для POST_
+_call / вызывает MainController::create для POST_
-_вызывает MainController::update для PUT_
+_call / вызывает MainController::update для PUT_
-_вызывает MainController::delete для DELETE_
+_call / вызывает MainController::delete для DELETE_
```php
$router->resource('api/:id', MainController::class);
```
-Изменить методы контроллера по умолчанию можно передав массив с вашими именами
+Изменить методы контроллера по умолчанию можно передав массив с вашими именами\
+You can change the default controller methods by passing an array with your names
```php
$router->resource('api/:id', MainController::class, ['actionIndex', 'actionAdd', 'actionUpdate', 'actionDrop']);
```
-##### Вариант объявления маршрута методом set
-#### Устанавливаем маршрут /test/:id для http методов DELETE|PUT
-_выполняет лямбда-функцию_
-```php
-$router->set(['/test/page', 'POST|PUT', function () {
- echo 'Hello world!';
- }
-]);
-```
-_вызывает MainController::actionIndex_
+#### A variant of declaring a route using the set method / Вариант объявления маршрута методом set
+_call / вызывает MainController::actionIndex_
```php
$router->set(['/test/:id', 'DELETE|PUT', [MainController::class, 'actionIndex'], [
'before' => [First::class, Second::class],
'after' => [[First::class], [Second::class]]
]]);
```
-_Пример Middleware_
+_Exemple / Пример Middleware_
```php
-next($middlewares);
- }
-
- public function next(array $middlewares): void
- {
- $this->handleMiddleware($middlewares);
- }
-}
-```
-_Пример Middleware с параметрами с использованием Фасада_
-```php
-next($middlewares);
- }
-
- public function next(array $middlewares): void
+ public function __invoke($params, $next)
{
- Router::handleMiddleware($middlewares);
+ // Logic here
+ $next();
}
}
```
diff --git a/docs.md b/docs.md
index 50ecb63f..02f23775 100644
--- a/docs.md
+++ b/docs.md
@@ -1,5 +1,4 @@
## Table of contents
-- [Rudra\Router\MiddlewareInterface](#rudra_router_middlewareinterface)
- [Rudra\Router\Router](#rudra_router_router)
- [Rudra\Router\RouterFacade](#rudra_router_routerfacade)
- [Rudra\Router\RouterInterface](#rudra_router_routerinterface)
@@ -8,40 +7,32 @@
- [Rudra\Router\Traits\RouterRequestMethodTrait](#rudra_router_traits_routerrequestmethodtrait)
-
-
-### Class: Rudra\Router\MiddlewareInterface
-| Visibility | Function |
-|:-----------|:---------|
-|abstract public|next( array $chainOfMiddlewares ): void
|
-
-
### Class: Rudra\Router\Router
-##### implements [Rudra\Router\RouterInterface](#rudra_router_routerinterface)
| Visibility | Function |
|:-----------|:---------|
-|public|set( array $route ): void
|
-|private|handleRequestUri( array $route ): void
|
-|private|handleRequestMethod(): void
|
-|private|handlePattern( array $route array $request ): array
|
-|private|setCallable( array $route $params ): void
|
-|public|directCall( array $route $params ): void
|
-|private|callActionThroughReflection( ?array $params string $action object $controller ): void
|
-|private|callActionThroughException( $params $action $controller ): void
|
-|public|handleMiddleware( array $chainOfMiddlewares ): void
|
-|public|annotationCollector( array $controllers bool $getter bool $attributes ): ?array
|
-|protected|handleAnnotationMiddleware( array $annotation ): array
|
-|public|__construct( Rudra\Container\Interfaces\RudraInterface $rudra )
|
-|public|rudra(): Rudra\Container\Interfaces\RudraInterface
|
-|public|get( array $route ): void
|
-|public|post( array $route ): void
|
-|public|put( array $route ): void
|
-|public|patch( array $route ): void
|
-|public|delete( array $route ): void
|
-|public|any( array $route ): void
|
-|public|resource( array $route array $actions ): void
|
+| public | `set(array $route): void`
Sets the route, parsing HTTP methods (if multiple are specified via \|).
Registers a route handler for each method.
-------------------------
Устанавливает маршрут, разбирая HTTP-методы (если указано несколько через \|).
Для каждого метода регистрирует обработчик маршрута. |
+| private | `handleRequestUri(array $route): void`
Processes the incoming URI request and checks if it matches the current route.
-------------------------
Обрабатывает входящий URI-запрос и проверяет его совпадение с текущим маршрутом. |
+| private | `handleRequestMethod(): void`
Processes the HTTP request method, including spoofing via _method (for PUT/PATCH/DELETE)
-------------------------
Обрабатывает HTTP-метод запроса, включая spoofing через _method (для PUT/PATCH/DELETE) |
+| private | `handlePattern(array $route, array $request): array`
Matches the URI from the route with the actual request, processing parameters of the form :param and :regexp.
This method is used to extract dynamic segments from a URI pattern:
-------------------------
Сопоставляет URI из маршрута с фактическим запросом, обрабатывая параметры вида :param и :regexp.
Метод извлекает динамические сегменты из URL-шаблона: |
+| private | `setCallable(array $route, ?array $params): void`
Calls the controller associated with the route — either a Closure or a controller method.
-------------------------
Вызывает контроллер, связанный с маршрутом — либо Closure, либо метод контроллера. |
+| public | `directCall(array $route, ?array $params): void`
Calls the controller and its method directly, performing the full lifecycle:
This method is used to fully dispatch a route after matching it with the current request.
-------------------------
Вызывает контроллер и его метод напрямую, выполняя полный жизненный цикл:
Метод используется для полной диспетчеризации маршрута после его совпадения с текущим запросом. |
+| private | `callActionThroughReflection(?array $params, string $action, object $controller): void`
Calls the controller method using Reflection, performing automatic parameter injection based on type hints.
This method is typically used when the zend.exception_ignore_args setting is enabled,
allowing for more flexible and type-safe dependency resolution.
-------------------------
Вызывает метод контроллера с помощью Reflection, выполняя автоматическое внедрение параметров на основе типизации.
Этот метод обычно используется, когда включена настройка zend.exception_ignore_args,
что позволяет более гибко и безопасно разрешать зависимости по типам. |
+| private | `callActionThroughException(?array $params, string $action, object $controller): void`
Calls the specified controller method directly.
If the argument type or number does not match — tries to automatically inject required dependencies.
This is a fallback mechanism for cases where Reflection-based injection is disabled or unavailable.
Handles two types of errors during invocation:
- \ArgumentCountError — thrown when the number of arguments doesn't match the method signature.
- \TypeError — thrown when an argument is not compatible with the expected type.
In both cases, Rudra's autowire system attempts to resolve and inject the correct dependencies.
-------------------------
Вызывает указанный метод контроллера напрямую.
Если тип или количество аргументов не совпадает — пытается автоматически внедрить нужные зависимости.
Это механизм отката, используемый, когда недоступен вызов через Reflection.
Обрабатываются следующие ошибки:
- \ArgumentCountError — выбрасывается, если количество аргументов не совпадает с ожидаемым.
- \TypeError — выбрасывается, если тип аргумента не соответствует ожидаемому.
В обоих случаях система автовайринга Rudra пытается разрешить и внедрить правильные зависимости. |
+| public | `handleMiddleware(array $chain): void`
Executes a chain of middleware, recursively calling each element.
Middleware can be specified in one of the supported formats:
- 'MiddlewareClass' (string) — a simple class name to call without parameters.
- ['MiddlewareClass'] (array with class name) — same as above, allows for future extensions.
- ['MiddlewareClass', \$parameter] (array with class and parameter) — passes the parameter to the middleware.
Each middleware must implement the __invoke() method to be callable.
--------------------
Выполняет цепочку middleware, рекурсивно вызывая каждый элемент.
Middleware может быть указан в одном из поддерживаемых форматов:
- 'MiddlewareClass' (строка) — простое имя класса без параметров.
- ['MiddlewareClass'] (массив с именем класса) — аналогично предыдущему, удобно для расширения.
- ['MiddlewareClass', \$parameter] (массив с классом и параметром) — передаёт параметр в middleware.
Каждый middleware должен реализовывать метод __invoke(), чтобы быть вызываемым. |
+| public | `annotationCollector(array $controllers, bool $getter, bool $attributes): ?array`
Collects and processes annotations from the specified controllers.
This method scans each controller class for Routing and Middleware annotations,
builds route definitions based on those annotations, and either:
- Registers them directly via `set()` (if \$getter = false), or
- Returns them as an array (if \$getter = true).
--------------------
Собирает и обрабатывает аннотации указанных контроллеров.
Метод сканирует каждый контроллер на наличие аннотаций Routing и Middleware,
формирует определения маршрутов и либо:
- Регистрирует их напрямую через `set()` (если \$getter = false),
- Возвращает как массив (если \$getter = true). |
+| protected | `handleAnnotationMiddleware(array $annotation): array`
Processes middleware annotations into a valid middleware format.
--------------------
Обрабатывает аннотации middleware в поддерживаемый формат.
```#[Middleware(name: "Auth", params: "admin")]```
в:
```['Auth', 'admin']``` |
+| public | `__construct(Rudra\Container\Interfaces\RudraInterface $rudra)`
|
+| public | `rudra(): Rudra\Container\Interfaces\RudraInterface`
|
+| public | `get(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the GET HTTP method.
--------------------
Регистрирует маршрут с использованием метода GET. |
+| public | `post(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the POST HTTP method.
--------------------
Регистрирует маршрут с использованием метода POST. |
+| public | `put(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the PUT HTTP method.
--------------------
Регистрирует маршрут с использованием метода PUT. |
+| public | `patch(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the PATCH HTTP method.
--------------------
Регистрирует маршрут с использованием метода PATCH. |
+| public | `delete(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the DELETE HTTP method.
--------------------
Регистрирует маршрут с использованием метода DELETE. |
+| public | `any(string $pattern, callable\|array $target, array $middleware): void`
Registers a route that supports all HTTP methods.
Sets the method to a pipe-separated string ('GET\|POST\|PUT\|PATCH\|DELETE'),
allowing the same route to handle multiple request types.
--------------------
Регистрирует маршрут, поддерживающий все HTTP-методы.
Устанавливает метод как строку с разделителем \| ('GET\|POST\|PUT\|PATCH\|DELETE'),
что позволяет использовать один маршрут для нескольких типов запросов. |
+| public | `resource(string $pattern, string $controller, array $actions): void`
Registers a resource route, mapping standard actions to controller methods.
Supports common CRUD operations by default:
- GET=> read
- POST => create
- PUT=> update
- DELETE => delete
Can be customized with an optional \$actions array.
--------------------
Регистрирует ресурсный маршрут, связывая стандартные действия с методами контроллера.
По умолчанию поддерживает CRUD-операции:
- GET=> read
- POST => create
- PUT=> update
- DELETE => delete
Может быть переопределён с помощью массива \$actions. |
+| protected | `setRoute(string $pattern, $target, string $httpMethod, array $middleware): void`
The method constructs a route definition and passes it to the `set()` method for registration.
--------------------
Метод формирует определение маршрута и передает его в метод `set()` для регистрации. |
@@ -49,7 +40,7 @@
### Class: Rudra\Router\RouterFacade
| Visibility | Function |
|:-----------|:---------|
-|public static|__callStatic( string $method array $parameters ): mixed
|
+| public static | `__callStatic(string $method, array $parameters): ?mixed`
|
@@ -57,8 +48,8 @@
### Class: Rudra\Router\RouterInterface
| Visibility | Function |
|:-----------|:---------|
-|abstract public|set( array $route ): void
|
-|abstract public|directCall( array $route $params ): void
|
+| abstract public | `set(array $route): void`
Sets the route, parsing HTTP methods (if multiple are specified via \|).
Registers a route handler for each method.
-------------------------
Устанавливает маршрут, разбирая HTTP-методы (если указано несколько через \|).
Для каждого метода регистрирует обработчик маршрута. |
+| abstract public | `directCall(array $route, ?array $params): void`
Calls the controller and its method directly, performing the full lifecycle:
This method is used to fully dispatch a route after matching it with the current request.
-------------------------
Вызывает контроллер и его метод напрямую, выполняя полный жизненный цикл:
Метод используется для полной диспетчеризации маршрута после его совпадения с текущим запросом. |
@@ -73,8 +64,8 @@
### Class: Rudra\Router\Traits\RouterAnnotationTrait
| Visibility | Function |
|:-----------|:---------|
-|public|annotationCollector( array $controllers bool $getter bool $attributes ): ?array
|
-|protected|handleAnnotationMiddleware( array $annotation ): array
|
+| public | `annotationCollector(array $controllers, bool $getter, bool $attributes): ?array`
Collects and processes annotations from the specified controllers.
This method scans each controller class for Routing and Middleware annotations,
builds route definitions based on those annotations, and either:
- Registers them directly via `set()` (if \$getter = false), or
- Returns them as an array (if \$getter = true).
--------------------
Собирает и обрабатывает аннотации указанных контроллеров.
Метод сканирует каждый контроллер на наличие аннотаций Routing и Middleware,
формирует определения маршрутов и либо:
- Регистрирует их напрямую через `set()` (если \$getter = false),
- Возвращает как массив (если \$getter = true). |
+| protected | `handleAnnotationMiddleware(array $annotation): array`
Processes middleware annotations into a valid middleware format.
--------------------
Обрабатывает аннотации middleware в поддерживаемый формат.
```#[Middleware(name: "Auth", params: "admin")]```
в:
```['Auth', 'admin']``` |
@@ -82,14 +73,14 @@
### Class: Rudra\Router\Traits\RouterRequestMethodTrait
| Visibility | Function |
|:-----------|:---------|
-|abstract public|set( array $route ): void
|
-|public|get( array $route ): void
|
-|public|post( array $route ): void
|
-|public|put( array $route ): void
|
-|public|patch( array $route ): void
|
-|public|delete( array $route ): void
|
-|public|any( array $route ): void
|
-|public|resource( array $route array $actions ): void
|
+| public | `get(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the GET HTTP method.
--------------------
Регистрирует маршрут с использованием метода GET. |
+| public | `post(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the POST HTTP method.
--------------------
Регистрирует маршрут с использованием метода POST. |
+| public | `put(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the PUT HTTP method.
--------------------
Регистрирует маршрут с использованием метода PUT. |
+| public | `patch(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the PATCH HTTP method.
--------------------
Регистрирует маршрут с использованием метода PATCH. |
+| public | `delete(string $pattern, callable\|array $target, array $middleware): void`
Registers a route with the DELETE HTTP method.
--------------------
Регистрирует маршрут с использованием метода DELETE. |
+| public | `any(string $pattern, callable\|array $target, array $middleware): void`
Registers a route that supports all HTTP methods.
Sets the method to a pipe-separated string ('GET\|POST\|PUT\|PATCH\|DELETE'),
allowing the same route to handle multiple request types.
--------------------
Регистрирует маршрут, поддерживающий все HTTP-методы.
Устанавливает метод как строку с разделителем \| ('GET\|POST\|PUT\|PATCH\|DELETE'),
что позволяет использовать один маршрут для нескольких типов запросов. |
+| public | `resource(string $pattern, string $controller, array $actions): void`
Registers a resource route, mapping standard actions to controller methods.
Supports common CRUD operations by default:
- GET=> read
- POST => create
- PUT=> update
- DELETE => delete
Can be customized with an optional \$actions array.
--------------------
Регистрирует ресурсный маршрут, связывая стандартные действия с методами контроллера.
По умолчанию поддерживает CRUD-операции:
- GET=> read
- POST => create
- PUT=> update
- DELETE => delete
Может быть переопределён с помощью массива \$actions. |
+| protected | `setRoute(string $pattern, $target, string $httpMethod, array $middleware): void`
The method constructs a route definition and passes it to the `set()` method for registration.
--------------------
Метод формирует определение маршрута и передает его в метод `set()` для регистрации. |
###### created with [Rudra-Documentation-Collector](#https://github.com/Jagepard/Rudra-Documentation-Collector)
diff --git a/src/MiddlewareInterface.php b/src/MiddlewareInterface.php
deleted file mode 100755
index 2ac95b2d..00000000
--- a/src/MiddlewareInterface.php
+++ /dev/null
@@ -1,19 +0,0 @@
-
- * @license https://mit-license.org/ MIT
- */
-
-namespace Rudra\Router;
-
-interface MiddlewareInterface
-{
- /**
- * @param array $chainOfMiddlewares
- * @return void
- */
- public function next(array $chainOfMiddlewares): void;
-}
diff --git a/src/Router.php b/src/Router.php
index 3a6a1301..7592ebe3 100755
--- a/src/Router.php
+++ b/src/Router.php
@@ -10,8 +10,8 @@
namespace Rudra\Router;
use ReflectionException;
-use Rudra\Exceptions\RouterException;
use Rudra\Container\Traits\SetRudraContainersTrait;
+use Rudra\Exceptions\{MiddlewareException, RouterException};
use Rudra\Router\Traits\{RouterAnnotationTrait, RouterRequestMethodTrait};
class Router implements RouterInterface
@@ -22,6 +22,16 @@ class Router implements RouterInterface
private array $reflectionCache = [];
+ /**
+ * Sets the route, parsing HTTP methods (if multiple are specified via |).
+ * Registers a route handler for each method.
+ * -------------------------
+ * Устанавливает маршрут, разбирая HTTP-методы (если указано несколько через |).
+ * Для каждого метода регистрирует обработчик маршрута.
+ *
+ * @param array $route
+ * @return void
+ */
public function set(array $route): void
{
$httpMethods = str_contains($route['method'], '|')
@@ -34,32 +44,46 @@ public function set(array $route): void
}
}
+ /**
+ * Processes the incoming URI request and checks if it matches the current route.
+ * -------------------------
+ * Обрабатывает входящий URI-запрос и проверяет его совпадение с текущим маршрутом.
+ *
+ * @param array $route
+ * @return void
+ */
private function handleRequestUri(array $route): void
{
$this->handleRequestMethod();
$request = $this->rudra->request();
- $server = $request->server();
+ $server = $request->server();
if ($route['method'] !== $server->get('REQUEST_METHOD')) {
return;
}
- $uriRaw = $server->get('REQUEST_URI');
- $parsed = parse_url($uriRaw);
- $requestPath = $parsed && isset($parsed['path']) ? ltrim($parsed['path'], '/') : '';
- $uriSegments = explode('/', $requestPath);
+ $uriRaw = $server->get('REQUEST_URI');
+ $parsed = parse_url($uriRaw);
+ $requestPath = $parsed && isset($parsed['path']) ? ltrim($parsed['path'], '/') : '';
+ $uriSegments = explode('/', $requestPath);
[$uri, $params] = $this->handlePattern($route, $uriSegments);
-
if ($uri === $uriSegments) {
$this->setCallable($route, $params);
}
}
+ /**
+ * Processes the HTTP request method, including spoofing via _method (for PUT/PATCH/DELETE)
+ * -------------------------
+ * Обрабатывает HTTP-метод запроса, включая spoofing через _method (для PUT/PATCH/DELETE)
+ *
+ * @return void
+ */
private function handleRequestMethod(): void
{
- $request = $this->rudra->request();
+ $request = $this->rudra->request();
$requestMethod = $request->server()->get('REQUEST_METHOD');
// Spoofing the method via _method parameter in POST requests
@@ -79,17 +103,28 @@ private function handleRequestMethod(): void
}
}
+ /**
+ * Matches the URI from the route with the actual request, processing parameters of the form :param and :regexp.
+ * This method is used to extract dynamic segments from a URI pattern:
+ * -------------------------
+ * Сопоставляет URI из маршрута с фактическим запросом, обрабатывая параметры вида :param и :regexp.
+ * Метод извлекает динамические сегменты из URL-шаблона:
+ *
+ * @param array $route
+ * @param array $request
+ * @return array
+ */
private function handlePattern(array $route, array $request): array
{
- $uri = [];
- $params = null;
+ $uri = [];
+ $params = null;
$subject = explode('/', ltrim($route['url'], '/'));
- $count = count($subject);
+ $count = count($subject);
for ($i = 0; $i < $count; $i++) {
if (preg_match("/^:[a-zA-Z0-9_-]+$/", $subject[$i]) > 0 && array_key_exists($i, $request)) {
- $value = $request[$i];
- $uri[] = $value;
+ $value = $request[$i];
+ $uri[] = $value;
$params[] = $value;
continue;
}
@@ -98,7 +133,7 @@ private function handlePattern(array $route, array $request): array
if (array_key_exists($i, $request)) {
$pattern = $matches[1];
if (preg_match("/^$pattern$/", $request[$i])) {
- $uri[] = $request[$i];
+ $uri[] = $request[$i];
$params[] = $request[$i];
} else {
$uri[] = '!@#$%^&*';
@@ -114,7 +149,16 @@ private function handlePattern(array $route, array $request): array
return [$uri, $params];
}
- private function setCallable(array $route, $params): void
+ /**
+ * Calls the controller associated with the route — either a Closure or a controller method.
+ * -------------------------
+ * Вызывает контроллер, связанный с маршрутом — либо Closure, либо метод контроллера.
+ *
+ * @param array $route
+ * @param array|null $params
+ * @return void
+ */
+ private function setCallable(array $route, ?array $params): void
{
if ($route['controller'] instanceof \Closure) {
if (is_array($params)) {
@@ -123,16 +167,32 @@ private function setCallable(array $route, $params): void
$route['controller']($params);
}
- exit();
+ if ($this->rudra->config()->get('environment') !== 'test') {
+ exit();
+ }
+
+ return;
}
$this->directCall($route, $params);
}
- public function directCall(array $route, $params = null): void
+ /**
+ * Calls the controller and its method directly, performing the full lifecycle:
+ * This method is used to fully dispatch a route after matching it with the current request.
+ * -------------------------
+ * Вызывает контроллер и его метод напрямую, выполняя полный жизненный цикл:
+ * Метод используется для полной диспетчеризации маршрута после его совпадения с текущим запросом.
+ *
+ * @param array $route
+ * @param array|null $params
+ * @return void
+ * @throws RouterException
+ */
+ public function directCall(array $route, ?array $params = null): void
{
$controller = $this->rudra->get($route['controller']);
- $action = $route['action'];
+ $action = $route['action'];
if (!method_exists($controller, $action)) {
throw new RouterException("503");
@@ -163,6 +223,23 @@ public function directCall(array $route, $params = null): void
}
}
+ /**
+ * Calls the controller method using Reflection, performing automatic parameter injection based on type hints.
+ *
+ * This method is typically used when the zend.exception_ignore_args setting is enabled,
+ * allowing for more flexible and type-safe dependency resolution.
+ * -------------------------
+ * Вызывает метод контроллера с помощью Reflection, выполняя автоматическое внедрение параметров на основе типизации.
+ *
+ * Этот метод обычно используется, когда включена настройка zend.exception_ignore_args,
+ * что позволяет более гибко и безопасно разрешать зависимости по типам.
+ *
+ * @param array|null $params
+ * @param string action
+ * @param object $controller
+ * @return void
+ * @throws RouterException
+ */
private function callActionThroughReflection(?array $params, string $action, object $controller): void
{
if ($params && in_array('', $params, true)) {
@@ -170,6 +247,7 @@ private function callActionThroughReflection(?array $params, string $action, obj
}
$cacheKey = get_class($controller) . "::$action";
+
if (!isset($this->reflectionCache[$cacheKey])) {
$this->reflectionCache[$cacheKey] = [
'method' => new \ReflectionMethod($controller, $action),
@@ -181,7 +259,36 @@ private function callActionThroughReflection(?array $params, string $action, obj
$method->invokeArgs($controller, $arguments);
}
- private function callActionThroughException($params, $action, $controller): void
+ /**
+ * Calls the specified controller method directly.
+ *
+ * If the argument type or number does not match — tries to automatically inject required dependencies.
+ * This is a fallback mechanism for cases where Reflection-based injection is disabled or unavailable.
+ *
+ * Handles two types of errors during invocation:
+ * - \ArgumentCountError — thrown when the number of arguments doesn't match the method signature.
+ * - \TypeError — thrown when an argument is not compatible with the expected type.
+ *
+ * In both cases, Rudra's autowire system attempts to resolve and inject the correct dependencies.
+ * -------------------------
+ * Вызывает указанный метод контроллера напрямую.
+ *
+ * Если тип или количество аргументов не совпадает — пытается автоматически внедрить нужные зависимости.
+ * Это механизм отката, используемый, когда недоступен вызов через Reflection.
+ *
+ * Обрабатываются следующие ошибки:
+ * - \ArgumentCountError — выбрасывается, если количество аргументов не совпадает с ожидаемым.
+ * - \TypeError — выбрасывается, если тип аргумента не соответствует ожидаемому.
+ *
+ * В обоих случаях система автовайринга Rudra пытается разрешить и внедрить правильные зависимости.
+ *
+ * @param array|null $params
+ * @param string $action
+ * @param object $controller
+ * @return void
+ * @throws RouterException
+ */
+ private function callActionThroughException(?array $params, string $action, object $controller): void
{
if (isset($params) && in_array('', $params)) {
throw new RouterException("404");
@@ -202,32 +309,64 @@ private function callActionThroughException($params, $action, $controller): void
}
}
- public function handleMiddleware(array $chainOfMiddlewares): void
+ /**
+ * Executes a chain of middleware, recursively calling each element.
+ *
+ * Middleware can be specified in one of the supported formats:
+ * - 'MiddlewareClass' (string) — a simple class name to call without parameters.
+ * - ['MiddlewareClass'] (array with class name) — same as above, allows for future extensions.
+ * - ['MiddlewareClass', $parameter] (array with class and parameter) — passes the parameter to the middleware.
+ *
+ * Each middleware must implement the __invoke() method to be callable.
+ * --------------------
+ * Выполняет цепочку middleware, рекурсивно вызывая каждый элемент.
+ *
+ * Middleware может быть указан в одном из поддерживаемых форматов:
+ * - 'MiddlewareClass' (строка) — простое имя класса без параметров.
+ * - ['MiddlewareClass'] (массив с именем класса) — аналогично предыдущему, удобно для расширения.
+ * - ['MiddlewareClass', $parameter] (массив с классом и параметром) — передаёт параметр в middleware.
+ *
+ * Каждый middleware должен реализовывать метод __invoke(), чтобы быть вызываемым.
+ *
+ * @param array $chain
+ * @return void
+ * @throws \Rudra\Router\Exceptions\MiddlewareException
+ */
+ public function handleMiddleware(array $chain): void
{
- if (!$chainOfMiddlewares) {
+ if (!$chain) {
return;
}
- $current = array_shift($chainOfMiddlewares);
+ $current = array_shift($chain);
- if (is_array($current) && count($current) === 2 && is_string($current[0])) {
- $middleware = new $current[0]();
- $middleware($current[1], $chainOfMiddlewares);
- return;
- }
+ try {
+ if (is_array($current) && count($current) === 2 && is_string($current[0])) {
+ $middleware = new $current[0]();
+ $middleware($chain, ...$current[1]);
+ return;
+ }
- if (is_array($current) && is_string($current[0])) {
- $middleware = new $current[0]();
- $middleware($chainOfMiddlewares);
- return;
- }
+ if (is_array($current) && is_string($current[0])) {
+ $middleware = new $current[0]();
+ $middleware($chain);
+ return;
+ }
- if (is_string($current)) {
- $middleware = new $current();
- $middleware($chainOfMiddlewares);
- return;
- }
+ if (is_string($current)) {
+ $middleware = new $current();
+ $middleware($chain);
+ return;
+ }
- throw new \InvalidArgumentException('Invalid middleware format');
+ if (is_callable($current)) {
+ $current($chain);
+ return;
+ }
+
+ throw new MiddlewareException('Invalid middleware format');
+ } catch (\Throwable $e) {
+ throw new MiddlewareException("Failed to process middleware: " . json_encode($current), 0, $e);
+ }
}
}
diff --git a/src/RouterInterface.php b/src/RouterInterface.php
index 3769528d..9ba96309 100755
--- a/src/RouterInterface.php
+++ b/src/RouterInterface.php
@@ -13,6 +13,29 @@
interface RouterInterface
{
+ /**
+ * Sets the route, parsing HTTP methods (if multiple are specified via |).
+ * Registers a route handler for each method.
+ * -------------------------
+ * Устанавливает маршрут, разбирая HTTP-методы (если указано несколько через |).
+ * Для каждого метода регистрирует обработчик маршрута.
+ *
+ * @param array $route
+ * @return void
+ */
public function set(array $route): void;
- public function directCall(array $route, $params = null): void;
+
+ /**
+ * Calls the controller and its method directly, performing the full lifecycle:
+ * This method is used to fully dispatch a route after matching it with the current request.
+ * -------------------------
+ * Вызывает контроллер и его метод напрямую, выполняя полный жизненный цикл:
+ * Метод используется для полной диспетчеризации маршрута после его совпадения с текущим запросом.
+ *
+ * @param array $route
+ * @param array|null $params
+ * @return void
+ * @throws RouterException
+ */
+ public function directCall(array $route, ?array $params = null): void;
}
diff --git a/src/Traits/RouterAnnotationTrait.php b/src/Traits/RouterAnnotationTrait.php
index 6582487b..c546562b 100755
--- a/src/Traits/RouterAnnotationTrait.php
+++ b/src/Traits/RouterAnnotationTrait.php
@@ -3,8 +3,8 @@
declare(strict_types=1);
/**
- * @author : Jagepard
- * @license https://mit-license.org/ MIT
+ * @author : Jagepard
+ * @license https://mit-license.org/ MIT
*/
namespace Rudra\Router\Traits;
@@ -15,10 +15,24 @@
trait RouterAnnotationTrait
{
/**
- * @param array $controllers
- * @param boolean $getter
- * @param boolean $attributes
- * @return void
+ * Collects and processes annotations from the specified controllers.
+ *
+ * This method scans each controller class for Routing and Middleware annotations,
+ * builds route definitions based on those annotations, and either:
+ * - Registers them directly via `set()` (if $getter = false), or
+ * - Returns them as an array (if $getter = true).
+ * --------------------
+ * Собирает и обрабатывает аннотации указанных контроллеров.
+ *
+ * Метод сканирует каждый контроллер на наличие аннотаций Routing и Middleware,
+ * формирует определения маршрутов и либо:
+ * - Регистрирует их напрямую через `set()` (если $getter = false),
+ * - Возвращает как массив (если $getter = true).
+ *
+ * @param array $controllers
+ * @param bool $getter
+ * @param bool $attributes
+ * @return array|null
*/
public function annotationCollector(array $controllers, bool $getter = false, bool $attributes = false): ?array
{
@@ -70,21 +84,29 @@ public function annotationCollector(array $controllers, bool $getter = false, bo
}
/**
+ * Processes middleware annotations into a valid middleware format.
+ * --------------------
+ * Обрабатывает аннотации middleware в поддерживаемый формат.
+ *
+ * ```#[Middleware(name: "Auth", params: "admin")]```
+ * в:
+ * ```['Auth', 'admin']```
+ *
* @param array $annotation
* @return array
*/
protected function handleAnnotationMiddleware(array $annotation): array
{
- $middleware = [];
+ $output = [];
- foreach ($annotation as $item) {
- $entry = [$item['name']];
- if (isset($item['params'])) {
- $entry[] = $item['params'];
+ foreach ($annotation as $middleware) {
+ if (!isset($middleware['params'])) {
+ $output[] = $middleware['name'];
+ } else {
+ $output[] = [$middleware['name'], $middleware['params']];
}
- $middleware[] = $entry;
}
- return $middleware;
+ return $output;
}
}
diff --git a/src/Traits/RouterRequestMethodTrait.php b/src/Traits/RouterRequestMethodTrait.php
index f4323ecf..80636c02 100755
--- a/src/Traits/RouterRequestMethodTrait.php
+++ b/src/Traits/RouterRequestMethodTrait.php
@@ -3,8 +3,8 @@
declare(strict_types=1);
/**
- * @author : Jagepard
- * @license https://mit-license.org/ MIT
+ * @author : Jagepard
+ * @license https://mit-license.org/ MIT
*/
namespace Rudra\Router\Traits;
@@ -12,26 +12,112 @@
trait RouterRequestMethodTrait
{
/**
+ * Registers a route with the GET HTTP method.
+ * --------------------
+ * Регистрирует маршрут с использованием метода GET.
+ *
+ * @param string $pattern
+ * @param array|callable $target
+ * @param array $middleware
+ */
+ public function get(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'GET', $middleware);
+ }
+
+ /**
+ * Registers a route with the POST HTTP method.
+ * --------------------
+ * Регистрирует маршрут с использованием метода POST.
+ *
* @param array $route
*/
- abstract public function set(array $route): void;
+ public function post(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'POST', $middleware);
+ }
- public function get(array $route): void { $route['method'] = 'GET'; $this->set($route); }
- public function post(array $route): void { $route['method'] = 'POST'; $this->set($route); }
- public function put(array $route): void { $route['method'] = 'PUT'; $this->set($route); }
- public function patch(array $route): void { $route['method'] = 'PATCH'; $this->set($route); }
- public function delete(array $route): void { $route['method'] = 'DELETE'; $this->set($route); }
+ /**
+ * Registers a route with the PUT HTTP method.
+ * --------------------
+ * Регистрирует маршрут с использованием метода PUT.
+ *
+ * @param array $route
+ */
+ public function put(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'PUT', $middleware);
+ }
- public function any(array $route): void {
- $route['method'] = 'GET|POST|PUT|PATCH|DELETE';
- $this->set($route);
+ /**
+ * Registers a route with the PATCH HTTP method.
+ * --------------------
+ * Регистрирует маршрут с использованием метода PATCH.
+ *
+ * @param array $route
+ */
+ public function patch(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'PATCH', $middleware);
}
/**
+ * Registers a route with the DELETE HTTP method.
+ * --------------------
+ * Регистрирует маршрут с использованием метода DELETE.
+ *
* @param array $route
- * @param array $actions
*/
- public function resource(array $route, array $actions = ['read', 'create', 'update', 'delete']): void
+ public function delete(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'DELETE', $middleware);
+ }
+
+ /**
+ * Registers a route that supports all HTTP methods.
+ *
+ * Sets the method to a pipe-separated string ('GET|POST|PUT|PATCH|DELETE'),
+ * allowing the same route to handle multiple request types.
+ * --------------------
+ * Регистрирует маршрут, поддерживающий все HTTP-методы.
+ *
+ * Устанавливает метод как строку с разделителем | ('GET|POST|PUT|PATCH|DELETE'),
+ * что позволяет использовать один маршрут для нескольких типов запросов.
+ *
+ * @param array $route
+ */
+ public function any(string $pattern, array|callable $target, array $middleware = []): void
+ {
+ $this->setRoute($pattern, $target, 'GET|POST|PUT|PATCH|DELETE', $middleware);
+ }
+
+ /**
+ * Registers a resource route, mapping standard actions to controller methods.
+ *
+ * Supports common CRUD operations by default:
+ * - GET => read
+ * - POST => create
+ * - PUT => update
+ * - DELETE => delete
+ *
+ * Can be customized with an optional $actions array.
+ * --------------------
+ * Регистрирует ресурсный маршрут, связывая стандартные действия с методами контроллера.
+ *
+ * По умолчанию поддерживает CRUD-операции:
+ * - GET => read
+ * - POST => create
+ * - PUT => update
+ * - DELETE => delete
+ *
+ * Может быть переопределён с помощью массива $actions.
+ *
+ * @param string $pattern
+ * @param string $controller
+ * @param array $actions
+ * @return void
+ */
+ public function resource(string $pattern, string $controller, array $actions = ['read', 'create', 'update', 'delete']): void
{
$request = $this->rudra->request();
$server = $request->server();
@@ -64,6 +150,44 @@ public function resource(array $route, array $actions = ['read', 'create', 'upda
return; // Неизвестный метод — игнорируем
}
+ $route['url'] = $pattern;
+ $route['controller'] = $controller;
+
+ $this->set($route);
+ }
+
+ /**
+ * The method constructs a route definition and passes it to the `set()` method for registration.
+ * --------------------
+ * Метод формирует определение маршрута и передает его в метод `set()` для регистрации.
+ *
+ * @param string $pattern
+ * @param mixed $target
+ * @param string $httpMethod
+ * @param array $middleware
+ */
+ protected function setRoute(string $pattern, $target, string $httpMethod, array $middleware = []): void
+ {
+ $route['method'] = $httpMethod;
+ $route['url'] = $pattern;
+
+ if (count($middleware)) {
+ if (array_key_exists('before', $middleware)) {
+ $route['middleware']['before'] = $middleware['before'];
+ }
+
+ if (array_key_exists('after', $middleware)) {
+ $route['middleware']['after'] = $middleware['after'];
+ }
+ }
+
+ if (is_callable($target)) {
+ $route['controller'] = $target;
+ } elseif (is_array($target)) {
+ $route['controller'] = $target[0];
+ $route['action'] = $target[1];
+ }
+
$this->set($route);
}
}
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index 91f785d4..77410774 100755
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -34,14 +34,7 @@ protected function setRouteEnvironment(string $requestUri, string $requestMethod
$action = "action" . ucfirst($method);
$this->setContainer();
- $route = [
- 'url' => $pattern,
- 'method' => $requestMethod,
- 'action' => "action" . ucfirst($method),
- 'controller' => $controller
- ];
-
- \Rudra\Router\RouterFacade::$method($route);
+ \Rudra\Router\RouterFacade::$method($pattern, [$controller, "action" . ucfirst($method)]);
$this->assertEquals($requestMethod, Rudra::config()->get($action));
}
@@ -86,12 +79,7 @@ public function testAny(): void
$_SERVER["REQUEST_METHOD"] = "PATCH";
$this->setContainer();
- Router::any([
- 'url' => '/test/page',
- 'action' => 'actionAny',
- 'controller' => MainController::class
- ]);
-
+ Router::any('/test/page',[MainController::class, 'actionAny']);
$this->assertEquals("ANY", Rudra::config()->get("actionAny"));
}
@@ -100,12 +88,7 @@ protected function setRouteResourceEnvironment(string $requestMethod, string $ac
$_SERVER["REQUEST_URI"] = "api/123";
$_SERVER["REQUEST_METHOD"] = $requestMethod;
$this->setContainer();
-
- Router::resource([
- 'url' => "api/:id",
- 'controller' => MainController::class
- ]);
-
+ Router::resource("api/:id", MainController::class);
$this->assertEquals($action, Rudra::config()->get($action));
}
@@ -123,12 +106,7 @@ protected function setRouteResourcePostEnvironment(string $requestMethod, string
$_SERVER["REQUEST_METHOD"] = "POST";
$_POST["_method"] = $requestMethod;
$this->setContainer();
-
- Router::resource([
- 'url' => "api/:id",
- 'controller' => MainController::class
- ]);
-
+ Router::resource("api/:id", MainController::class);
$this->assertEquals($action, Rudra::config()->get($action));
}
@@ -148,11 +126,7 @@ protected function setRoutePostEnvironment(string $requestMethod, string $action
$method = strtolower($requestMethod);
- Router::resource([
- 'url' => "api/:id",
- 'controller' => MainController::class
- ]);
-
+ Router::resource("api/:id", MainController::class);
$this->assertEquals($action, Rudra::config()->get($action));
}
@@ -169,17 +143,15 @@ public function testMiddleware()
$_SERVER["REQUEST_METHOD"] = "GET";
$this->setContainer();
- Router::get([
- 'url' => "123/:id",
- 'controller' => MainController::class,
- 'action' => 'read',
- 'middleware' => [
+ Router::get("123/:id", [MainController::class,'read'],
+ [
"before" => [[Middleware::class]],
- "after" => [[Middleware::class]]
+ "after" => [function () { Rudra::config()->set(["after" => __FUNCTION__]); }]
]
- ]);
+ );
$this->assertEquals(Middleware::class, Rudra::config()->get("middleware"));
+ $this->assertEquals("{closure:Rudra\Router\Tests\RouterTest::testMiddleware():149}", Rudra::config()->get("after"));
}
public function testClosure()
@@ -188,15 +160,20 @@ public function testClosure()
$_SERVER["REQUEST_METHOD"] = "GET";
$this->setContainer();
- Rudra::config()->set(["environment" => "test"]);
-
- Router::get([
- 'url' => "test/page",
- 'controller' => function () {
+ Router::get("test/page", function () {
Rudra::config()->set(["closure" => "closure"]);
- }
- ]);
+ });
$this->assertEquals("closure", Rudra::config()->get("closure"));
}
+
+ public function testRegex(): void
+ {
+ $_SERVER["REQUEST_URI"] = "test/12";
+ $_SERVER["REQUEST_METHOD"] = "GET";
+ $this->setContainer();
+
+ Router::get("test/:[\d]{1,3}", [MainController::class, 'actionRegexGet']);
+ $this->assertEquals('regex', Rudra::config()->get("regex"));
+ }
}
diff --git a/tests/Stub/Controllers/MainController.php b/tests/Stub/Controllers/MainController.php
index a2bbb0ce..d9cbc17f 100755
--- a/tests/Stub/Controllers/MainController.php
+++ b/tests/Stub/Controllers/MainController.php
@@ -61,6 +61,11 @@ public function delete($params)
Rudra::config()->set(["delete" => "delete"]);
}
+ public function actionRegexGet()
+ {
+ Rudra::config()->set(["regex" => "regex"]);
+ }
+
public function shipInit() {}
public function containerInit() {}
public function init() {}