Download the PHP package phpsoftbox/router without Composer
On this page you can find all versions of the php package phpsoftbox/router. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download phpsoftbox/router
More information about phpsoftbox/router
Files in phpsoftbox/router
Package router
Short Description Router component for the PhpSoftBox framework
License MIT
Informations about the package router
Routing
Лёгкий роутер PhpSoftBox позволяет регистрировать маршруты, группировать их, навешивать middleware, валидировать параметры и генерировать URL по имени маршрута.
Состав пакета:
PhpSoftBox\Router\RouteCollector— регистрация маршрутов, групп, ресурсных маршрутов, глобальных middleware.PhpSoftBox\Router\RouteResolver— поиск подходящего маршрута по PSR-7 запросу.PhpSoftBox\Router\Dispatcher— исполнение обработчика маршрута с учётом middleware.PhpSoftBox\Router\Router— PSR-15 RequestHandler (resolve + dispatch).PhpSoftBox\Router\UrlGenerator— генерация URL по имени маршрута.PhpSoftBox\Router\RequestContext— контекст запроса для генерации абсолютных URL.PhpSoftBox\Router\Handler\ContainerHandlerResolver— резолвер обработчиков через DI-контейнер (PSR-11).PhpSoftBox\Router\ParamTypesEnum— встроенные валидаторы параметров маршрута.
Мы используем собственные реализации PSR-7/PSR-17 (PhpSoftBox\Http\Message\*).
Быстрый старт
Регистрация маршрутов
get(post|put|delete|patch|head|options|any)(string $path, callable|array|string $handler): RouteBuildergroup(callable $callback): RouteGroupBuilderimport(string $pathWithoutExtension): callableimportGroup(string $pathWithoutExtension): RouteGroupBuilderresource(string $path, string $controller): ResourceBuilderaddControllerMiddleware(string $controller, array $middlewares, array $only = [], array $except = [])
В middleware можно передавать как экземпляры, так и строки (alias, группа или class‑string).
Middleware для контроллеров
Рекомендуется вешать middleware на маршруты или группы; контроллеры/экшены — для точечных случаев.
addControllerMiddleware() и addMiddleware() (глобальный middleware коллектора) применяются ко всем маршрутам
коллектора — в том числе зарегистрированным раньше вызова: итоговый список middleware собирается в
getRoutes()/getNamedRoutes(), а не в момент регистрации маршрута. Поэтому auth, объявленный после загрузки
route-файлов, не теряется.
Примеры
Группы и middleware
Порядок и повторный вызов middleware
- Middleware маршрута выполняются в порядке: глобальные (
addMiddleware), групповые, контроллерные (addControllerMiddleware), собственные middleware маршрута; затем обработчик. Dispatcherне расходует стек:RequestHandlerInterface, переданный вprocess(), при каждом вызовеhandle()заново проходит весь оставшийся стек. Middleware с повтором (retry, транзакции) может вызывать$handler->handle()несколько раз — middleware ниже него (auth, CSRF) выполнятся при каждом вызове.
Resource (CRUD) маршруты
Автонейминг маршрутов
Если имя не задано явно, оно генерируется автоматически по пути и методу.
Примеры:
Конфликты
- Если два маршрута получают одинаковое имя, выбрасывается исключение.
- Например:
GET /usersиGET /users/indexоба дадутusers.index.
Как избежать конфликтов
- Используйте
group(...)->prefix('/api')->apply()— префикс группы попадёт в имя (api.users.index). - Задавайте
nameявно для нестандартных маршрутов (health,metrics). - Для
resource(...)задавайтеnamePrefix, чтобы контролировать неймспейс.
Можно передавать строки вместо экземпляров middleware, если диспетчер умеет их резолвить:
Параметры маршрута
Поддержанные формы:
{id}— обязательный параметр одного сегмента, например/users/42;{slug?}— опциональный параметр одного сегмента, например/blogили/blog/post-1;{path*}— обязательный wildcard-параметр, захватывает один или несколько сегментов;{path*?}— опциональный wildcard-параметр, захватывает ноль или больше сегментов.
Правила wildcard:
- wildcard-параметр должен быть последним сегментом маршрута;
{path*}не матчится на/docs, потому что нужен хотя бы один сегмент;{path*?}матчится и на/docs, и на/docs/a/b;- значение попадает в validators и request attributes без leading slash;
%2Fвнутри wildcard-значения после декодирования неотличим от разделителя сегментов;- route cache сохраняет wildcard-маршруты как обычные маршруты.
Валидация параметров
Валидатор — значение ParamTypesEnum (INT — только цифры, STRING — любое значение сегмента), его строковое
значение ('int', 'string' — в таком виде валидаторы хранит кеш маршрутов) или callable, получающий строку и
возвращающий bool. Прочие значения при матчинге дают InvalidArgumentException.
Значения параметров декодируются из percent-encoding (rawurldecode()) до валидации: запрос
/tags/a%2Fb%20c для /tags/{name} даёт name = "a/b c", валидаторы и обработчик получают декодированную строку.
Пропущенный опциональный параметр в матч не попадает — используется значение из defaults(...), если оно задано.
Поведение
- Маршруты проверяются в порядке регистрации; подходит первый, у которого совпали host, путь, валидаторы и метод.
- Маршрут, параметр которого не прошёл валидатор, считается несовпавшим: поиск продолжается. Поэтому
/items/{id}сT::INT, зарегистрированный раньше/items/new, не делает/items/newнедостижимым. InvalidRouteParameterException(404; сообщение включает имя параметра) бросается, только если ни один маршрут не подошёл, но путь совпал хотя бы с одним маршрутом, отклонённым валидатором.- Несоответствие пути/хоста ведёт к отсутствию маршрута (404); если путь совпал, но метод не подходит ни одному
маршруту —
MethodNotAllowedException(405) со списком допустимых методов. HEAD-запрос без явногоhead(...)/any(...)-маршрута для пути обслуживается GET-маршрутом; если GET есть среди допустимых методов 405, в список добавляется иHEAD. Обработчик выполняется как для GET — тело ответа на HEAD отбрасывает эмиттер/SAPI (веб-сервер), роутер его не очищает.- После match роутер кладет параметры в request attribute
_route_paramsи дублирует каждый параметр отдельным attribute по имени параметра. - Если
ContainerHandlerResolverвыполняет entity binding,_route_paramsобновляется найденными сущностями. Это позволяет внешним компонентам, включаяphpsoftbox/auth, читать актуальные route params через bridge-provider без прямой зависимости от Router.
Генерация URL: UrlGenerator::generate()
Настройка контекста запроса:
Правила
- Обязательные плейсхолдеры
{param}должны быть предоставлены — иначеRouteNotFoundException. - Опциональные сегменты
/{param?}удаляются, если параметр не передан. - Значения параметров кодируются через
rawurlencode():generate('tag', ['name' => 'a/b?c#d'])для/tags/{name}даёт/tags/a%2Fb%3Fc%23d, поэтому значение не может изменить путь, добавить query или fragment. Передавайте исходные (не закодированные) значения — иначе получится двойное кодирование. - Wildcard-плейсхолдеры
{path*}и{path*?}подставляются без leading/trailing slash и кодируются посегментно: разделители/сохраняются ('guide/a b'→guide/a%20b). - В пути нормализуются повторяющиеся слеши, завершающий слеш отбрасывается (кроме корня).
- Третий аргумент
bool $shouldAbsolute = falseвключает абсолютный URL. - Четвертый аргумент
?string $host = nullпозволяет явно выбрать host для абсолютного URL. - Если у маршрута есть
host(...)и текущий host изRequestContextвходит в список допустимых, используется текущий host. - Если у маршрута есть
host(...), но текущий host не задан или не входит в список допустимых, используется первый host маршрута. - Если у маршрута нет ограничения по host, используется host из
RequestContext. - Если host не удалось определить, абсолютная генерация возвращает относительный URL.
Данные маршрута в request attributes
id/slugи прочие параметры маршрута кладутся вattributes.- Wildcard-параметры кладутся туда же, например
path = "guide/install". - Дополнительно доступны
_route(имя или путь маршрута) и_route_params(все параметры).
Авто‑резолв сущностей (EntityInterface)
Если параметр контроллера типизирован сущностью ORM (EntityInterface), контейнер автоматически подгружает сущность по параметру маршрута, имя которого совпадает с именем аргумента:
По умолчанию используется EntityManagerInterface::find(). Для расширенной загрузки используйте единый атрибут #[ResolveEntity]:
При withDeleted: true Router использует EntityManagerInterface::findWithDeleted().
Этот путь учитывает IdentityMap текущего UnitOfWork, поэтому повторный route lookup
возвращает уже managed-экземпляр и безопасно догружает relations в него.
Для lookup по физической колонке вместо primary key укажите column. Например, маршрут
GET /articles/{article} может резолвить сущность по slug:
Параметр column совместим с withDeleted и with. Идентификатор колонки экранируется
активным DB-драйвером, а значение маршрута передаётся как bound parameter. Числовые строки
при lookup по колонке сохраняются строками.
WithDeleted остаётся для обратной совместимости, но новый код лучше писать через ResolveEntity.
Scoped bindings (проверка связей между сущностями)
Чтобы автоматически проверять связь между вложенными сущностями, используйте scopeBindings():
При включённом scopeBindings сначала резолвятся все сущности, затем проверяется их связь по цепочке (parent → child). Если связь не найдена — выбрасывается InvalidRouteParameterException (404).
Поддерживаемые типы связей: many_to_one, has_one, has_many, belongs_to_many, has_many_through, morph_many, morph_to.
Метаданные связей Router получает только через публичный контракт
EntityManagerInterface::metadataProvider(). Поэтому scoped bindings совместимы с
entity-aware registry, tenant-менеджерами и другими proxy/wrapper-реализациями entity manager.
Внутренние методы конкретной реализации EntityManager не являются частью интеграционного
контракта Router.
По умолчанию проверка пытается использовать ORM‑метаданные связей. Для кастомной логики можно зарегистрировать свой resolver:
Интеграция
Routerреализует PSR-15RequestHandlerInterfaceи работает с нашими PSR-7/17 реализациями (PhpSoftBox\Http\Message\*).- Для DI можно прокидывать
RouteCollectorвRouteResolver, затем собратьRouter:
Пример DI-резолвера обработчиков (PSR-11)
Если контейнер поддерживает call() (например PHP-DI), он будет использован для инъекций в методы.
Аргументы обработчиков и API-схемы
ContainerHandlerResolver создаёт один PhpSoftBox\Request\Request на текущий
PSR-7 request и разрешает аргументы обработчика через цепочку
HandlerParameterResolverInterface. Встроенная цепочка поддерживает:
- PSR-7
ServerRequestInterface; Request;- наследников
RequestSchema; - наследников payload-only
ApiSchema; - совместимые типизированные объекты из request attributes.
ApiSchema можно объявить обычным аргументом Action. Router получает payload из
ApiSchemaPayloadResolverInterface, создаёт схему через container->make(),
разрешает остальные зависимости конструктора и вызывает validate() до Action:
По умолчанию payload равен Request::all(). Чтобы выбрать только body, query или
другой источник, зарегистрируйте свой ApiSchemaPayloadResolverInterface в
контейнере. Action при ValidationException не запускается.
Проектные resolvers передаются вторым аргументом конструктора и выполняются до встроенных:
CLI
Кеш маршрутов
Кеш сохраняется через CacheInterface. В кеш попадают только обработчики
в виде Class::method или invokable‑класс, а middleware должны быть строками
(alias, группа или class‑string). Замыкания и кастомные валидаторы не поддерживаются.
В кеш записывается итоговый список middleware маршрута (включая глобальные и контроллерные), поэтому к коллектору,
загруженному из кеша, не нужно повторно применять addMiddleware()/addControllerMiddleware() — middleware
продублируются.
All versions of router with dependencies
phpsoftbox/profiler Version ^1.0
phpsoftbox/request Version ^1.0
phpsoftbox/validator Version ^1.0
psr/container Version ^2.0
psr/http-message Version ^2.0
psr/http-server-handler Version ^1.0
psr/http-server-middleware Version ^1.0
psr/simple-cache Version ^3.0