http router
v2.16.2
PSR路由器,帶註釋的路由器,帶有屬性的路由器, PHP路由器。
composer require ' sunrise/http-router:^2.15 ' composer require ' sunrise/http-router-openapi:^2.0 '可以在此處找到更多詳細信息:Sunrise/HTTP-Router-Openapi。
此示例使用其他日出軟件包,但是您可以使用zend/diactoros或任何其他包裹。
composer require sunrise/http-message sunrise/http-server-request use Sunrise Http Message ResponseFactory ;
use Sunrise Http Router RouteCollector ;
use Sunrise Http Router Router ;
use Sunrise Http ServerRequest ServerRequestFactory ;
use function Sunrise Http Router emit ;
$ collector = new RouteCollector ();
// PSR-15 request handler (optimal performance):
$ collector -> get ( ' home ' , ' / ' , new HomeRequestHandler ());
// or you can use an anonymous function as your request handler:
$ collector -> get ( ' home ' , ' / ' , function ( $ request ) {
return ( new ResponseFactory )-> createResponse ( 200 );
});
// or you can use the name of a class that implements PSR-15:
$ collector -> get ( ' home ' , ' / ' , HomeRequestHandler::class);
// or you can use a class method name as your request handler:
// (note that such a class mayn't implement PSR-15)
$ collector -> get ( ' home ' , ' / ' , [HomeRequestHandler::class, ' index ' ]);
// most likely you will need to use PSR-11 container:
// (note that only named classes will be pulled from such a container)
$ collector -> setContainer ( $ container );
$ router = new Router ();
$ router -> addRoute (... $ collector -> getCollection ()-> all ());
$ request = ServerRequestFactory:: fromGlobals ();
$ response = $ router -> handle ( $ request );
emit ( $ response );研究日出/令人敬畏的skeleton,以了解如何使用它。
請注意,由於必須使用2.10.0類
ConfigLoader版本。
use Sunrise Http Router Loader ConfigLoader ;
use Sunrise Http Router Router ;
$ loader = new ConfigLoader ();
// set container if necessary...
$ loader -> setContainer ( $ container );
// attach configs...
$ loader -> attach ( ' routes/api.php ' );
$ loader -> attach ( ' routes/admin.php ' );
$ loader -> attach ( ' routes/public.php ' );
// or attach a directory...
// [!] available from version 2.2
$ loader -> attach ( ' routes ' );
// or attach an array...
// [!] available from version 2.4
$ loader -> attachArray ([
' routes/api.php ' ,
' routes/admin.php ' ,
' routes/public.php ' ,
]);
// install container if necessary...
$ loader -> setContainer ( $ container );
$ router = new Router ();
$ router -> load ( $ loader );
// if the router matching should be isolated for top middlewares...
// for example for error handling...
// [!] available from version 2.8
$ response = $ router -> run ( $ request );
// if the router is used as a request handler
$ response = $ router -> handle ( $ request );
// if the router is used as middleware
$ response = $ router -> process ( $ request , $ handler ); /** @var SunriseHttpRouterRouteCollector $this */
$ this -> get ( ' home ' , ' / ' , new CallableRequestHandler ( function ( $ request ) {
return ( new ResponseFactory )-> createJsonResponse ( 200 );
}));
// or using a direct reference to a request handler...
$ this -> get ( ' home ' , ' / ' , new App Http Controller HomeController ());請注意,由於版本2.10.0,您可以以不同的方式參考請求處理程序。
/** @var SunriseHttpRouterRouteCollector $this */
$ this -> get ( ' home ' , ' / ' , function ( $ request ) {
return ( new ResponseFactory )-> createJsonResponse ( 200 );
});
$ this -> get ( ' home ' , ' / ' , App Http Controller HomeController::class, [
App Http Middleware FooMiddleware::class,
App Http Middleware BarMiddleware::class,
]);
$ this -> get ( ' home ' , ' / ' , [ App Http Controller HomeController::class, ' index ' ], [
App Http Middleware FooMiddleware::class,
App Http Middleware BarMiddleware::class,
]);如果要使用註釋,請安裝學說/註釋軟件包:
composer require doctrine/annotations請注意,由於必須使用2.10.0類
DescriptorLoader。
請注意,由於版本2.10.0,您可以將@rote()註釋綁定到類方法。
use Doctrine Common Annotations AnnotationRegistry ;
use Sunrise Http Router Loader DescriptorLoader ;
use Sunrise Http Router Router ;
// necessary if you will use annotations (annotations isn't attributes)...
AnnotationRegistry:: registerLoader ( ' class_exists ' );
$ loader = new DescriptorLoader ();
// set container if necessary...
$ loader -> setContainer ( $ container );
// attach a directory with controllers...
$ loader -> attach ( ' src/Controller ' );
// or attach an array
// [!] available from version 2.4
$ loader -> attachArray ([
' src/Controller ' ,
' src/Bundle/BundleName/Controller ' ,
]);
// or attach a class only
// [!] available from 2.10 version.
$ loader -> attach ( App Http Controller FooController::class);
$ router = new Router ();
$ router -> load ( $ loader );
// if the router matching should be isolated for top middlewares...
// for example for error handling...
// [!] available from version 2.8
$ response = $ router -> run ( $ request );
// if the router is used as a request handler
$ response = $ router -> handle ( $ request );
// if the router is used as middleware
$ response = $ router -> process ( $ request , $ handler ); use Sunrise Http Router Annotation as Mapping ;
#[ Mapping Prefix( ' /api/v1 ' )]
#[ Mapping Middleware(SomeMiddleware::class)]
class SomeController {
#[ Mapping Route( ' foo ' , path: ' /foo ' )]
public function foo () {
// will be available at: /api/v1/foo
}
#[ Mapping Route( ' bar ' , path: ' /bar ' )]
public function bar () {
// will be available at: /api/v1/bar
}
} use App Controller HomeController ;
use Sunrise Http Router RouteCollector ;
use Sunrise Http Router Router ;
$ collector = new RouteCollector ();
// set container if necessary...
$ collector -> setContainer ( $ container );
$ collector -> get ( ' home ' , ' / ' , new HomeController ());
$ router = new Router ();
$ router -> addRoute (... $ collector -> getCollection ()-> all ());
// if the router matching should be isolated for top middlewares...
// for example for error handling...
// [!] available from version 2.8
$ response = $ router -> run ( $ request );
// if the router is used as a request handler
$ response = $ router -> handle ( $ request );
// if the router is used as middleware
$ response = $ router -> process ( $ request , $ handler ); use Sunrise Http Message ResponseFactory ;
use Sunrise Http Router Exception MethodNotAllowedException ;
use Sunrise Http Router Exception RouteNotFoundException ;
use Sunrise Http Router Middleware CallableMiddleware ;
use Sunrise Http Router RequestHandler CallableRequestHandler ;
use Sunrise Http Router RouteCollector ;
use Sunrise Http Router Router ;
use Sunrise Http ServerRequest ServerRequestFactory ;
use function Sunrise Http Router emit ;
$ collector = new RouteCollector ();
$ collector -> get ( ' home ' , ' / ' , new CallableRequestHandler ( function ( $ request ) {
return ( new ResponseFactory )-> createJsonResponse ( 200 );
}));
$ router = new Router ();
$ router -> addRoute (... $ collector -> getCollection ()-> all ());
$ router -> addMiddleware ( new CallableMiddleware ( function ( $ request , $ handler ) {
try {
return $ handler -> handle ( $ request );
} catch ( MethodNotAllowedException $ e ) {
return ( new ResponseFactory )-> createResponse ( 405 );
} catch ( RouteNotFoundException $ e ) {
return ( new ResponseFactory )-> createResponse ( 404 );
} catch ( Throwable $ e ) {
return ( new ResponseFactory )-> createResponse ( 500 );
}
}));
emit ( $ router -> run (ServerRequestFactory:: fromGlobals ())); $ collector = new RouteCollector ();
/** @var PsrContainerContainerInterface $container */
// Pass DI container to the collector...
$ collector -> setContainer ( $ container );
// Objects passed as strings will be initialized through the DI container...
$ route = $ collector -> get ( ' home ' , ' / ' , HomeController::class, [
FooMiddleware::class,
BarMiddleware::class,
]); $ loader = new ConfigLoader ();
/** @var PsrContainerContainerInterface $container */
// Pass DI container to the loader...
$ loader -> setContainer ( $ container );
// All found objects which has been passed as strings will be initialized through the DI container...
$ routes = $ loader -> load (); $ loader = new DescriptorLoader ();
/** @var PsrContainerContainerInterface $container */
// Pass DI container to the loader...
$ loader -> setContainer ( $ container );
// All found objects will be initialized through the DI container...
$ routes = $ loader -> load (); $ loader = new DescriptorLoader ();
/** @var PsrSimpleCacheCacheInterface $cache */
// Pass a cache to the loader...
$ loader -> setCache ( $ cache ); /**
* @Route(
* name="api_v1_entry_update",
* path="/api/v1/entry/{id<@uuid>}(/{optionalAttribute})",
* methods={"PATCH"},
* )
*/
final class EntryUpdateRequestHandler implements RequestHandlerInterface /**
* @Route(
* name="api_v1_entry_update",
* host="api.host",
* path="/api/v1/entry/{id<@uuid>}(/{optionalAttribute})",
* methods={"PATCH"},
* middlewares={
* "AppMiddlewareCorsMiddleware",
* "AppMiddlewareApiAuthMiddleware",
* },
* attributes={
* "optionalAttribute": "defaultValue",
* },
* summary="Updates an entry by UUID",
* description="Here you can describe the method in more detail...",
* tags={"api", "entry"},
* priority=0,
* )
*/
final class EntryUpdateRequestHandler implements RequestHandlerInterface /**
* @Route(
* name="home",
* path="/",
* method="GET",
* )
*/ use Sunrise Http Router Annotation Route ;
#[Route(
name: ' api_v1_entry_update ' ,
path: ' /api/v1/entry/{id<@uuid>}(/{optionalAttribute}) ' ,
methods: [ ' PATCH ' ],
)]
final class EntryUpdateRequestHandler implements RequestHandlerInterface use Sunrise Http Router Annotation Route ;
#[Route(
name: ' api_v1_entry_update ' ,
host: ' api.host ' ,
path: ' /api/v1/entry/{id<@uuid>}(/{optionalAttribute}) ' ,
methods: [ ' PATCH ' ],
middlewares: [
App Middleware CorsMiddleware::class,
App Middleware ApiAuthMiddleware::class,
],
attributes: [
' optionalAttribute ' => ' defaultValue ' ,
],
summary: ' Updates an entry by UUID ' ,
description: ' Here you can describe the method in more detail... ' ,
tags: [ ' api ' , ' entry ' ],
priority: 0 ,
)]
final class EntryUpdateRequestHandler implements RequestHandlerInterface use Sunrise Http Router Annotation Host ;
#[Host( ' admin ' )]
#[Prefix( ' /api/v1 ' )]
#[Postfix( ' .json ' )]
#[Middleware(SomeMiddleware::class)]
final class SomeController
{
#[Route( ' foo ' , ' /foo ' )]
public function foo ( ServerRequestInterface $ request ) : ResponseInterface
{
// this action will be available at:
// http://admin.host/api/v1/foo.json
//
// this can be handy to reduce code duplication...
}
} use Sunrise Http Router Middleware JsonPayloadDecodingMiddleware ;
$ router -> addMiddleware ( new JsonPayloadDecodingMiddleware ()); // checks if a route is exists
$ router -> hasRoute ( ' foo ' );
// gets a route by name
$ router -> getRoute ( ' foo ' );可從2.12版中獲得。
$ router -> getMatchedRoute ();可從1.x版中獲得,但沒有記錄在...
$ request -> getAttribute ( ' @route ' );
// or
$ request -> getAttribute ( Sunrise Http Router RouteInterface:: ATTR_ROUTE );可從版本2.13獲得。
$ eventDispatcher -> addListener (RouteEvent:: NAME , function ( RouteEvent $ event ) {
$ event -> getRoute ();
}); $ uri = $ router -> generateUri ( ' route.name ' , [
' attribute ' => ' value ' ,
], true ); $ response = $ router -> getRoute ( ' route.name ' )-> handle ( $ request );這裡註釋的示例。
$ collector -> group ( function ( $ collector ) {
$ collector -> group ( function ( $ collector ) {
$ collector -> group ( function ( $ collector ) {
$ collector -> get ( ' api.entry.read ' , ' /{id<d+>} ' , ...)
-> addMiddleware (...); // add the middleware(s) to the route...
})
-> addPrefix ( ' /entry ' ) // add the prefix to the group...
-> prependMiddleware (...); // add the middleware(s) to the group...
}, [
App Http Middleware Bar::class, // resolvable middlewares...
])
-> addPrefix ( ' /v1 ' ) // add the prefix to the group...
-> prependMiddleware (...); // add the middleware(s) to the group...
}, [
App Http Middleware Foo::class, // resolvable middlewares...
])
-> addPrefix ( ' /api ' ) // add the prefix to the group...
-> prependMiddleware (...); // add the middleware(s) to the group... $ collector -> get ( ' api.entry.read ' , ' /api/v1/entry/{id<d+>}(/{optional<w+>}) ' ); // @uuid pattern
$ collector -> get ( ' api.entry.read ' , ' /api/v1/entry/{id<@uuid>} ' );
// @slug pattern
$ collector -> get ( ' api.entry.read ' , ' /api/v1/entry/{slug<@slug>} ' );
// Custom patterns (available from version 2.9.0):
Sunrise Http Router Router:: $ patterns [ ' @id ' ] = ' [1-9][0-9]* ' ;
// Just use the custom pattern...
$ collector -> get ( ' api.entry.read ' , ' /api/v1/entry/{id<@id>} ' );最好通過路由器設置模式:
// available since version 2.11.0
$ router -> addPatterns ([
' @id ' => ' [1-9][0-9]* ' ,
]);...或通過路由器的構建器:
// available since version 2.11.0
$ builder -> setPatterns ([
' @id ' => ' [1-9][0-9]* ' ,
]);注意:如果您沒有為路線分配主機,則可以在任何主機上使用!
// move the hosts table into the settings...
$ router -> addHost ( ' public.host ' , ' www.example.com ' , ...);
$ router -> addHost ( ' admin.host ' , ' secret.example.com ' , ...);
$ router -> addHost ( ' api.host ' , ' api.example.com ' , ...);
// ...or:
$ router -> addHosts ([
' public.host ' => [ ' www.example.com ' , ...],
...
]);
// the route will available only on the `secret.example.com` host...
$ route -> setHost ( ' admin.host ' );
// routes in the group will available on the `secret.example.com` host...
$ collector -> group ( function ( $ collector ) {
// some code...
})
-> setHost ( ' admin.host ' );您可以從2.14.0版本以下解析主機名:
$ router -> addHost ( ' admin ' , ' www1.admin.example.com ' , ' www2.admin.example.com ' );
$ router -> resolveHostname ( ' www1.admin.example.com ' ); // return "admin"
$ router -> resolveHostname ( ' www2.admin.example.com ' ); // return "admin"
$ router -> resolveHostname ( ' unknown ' ); // return null另外,您可以通過主機名獲得所有路線:
$ router -> getRoutesByHostname ( ' www1.admin.example.com ' ); $ route -> getHolder (); // return Reflector (class, method or function) $ router = ( new RouterBuilder )
-> setEventDispatcher (...) // null or use to symfony/event-dispatcher...
-> setContainer (...) // null or PSR-11 container instance...
-> setCache (...) // null or PSR-16 cache instance... (only for descriptor loader)
-> setCacheKey (...) // null or string... (only for descriptor loader)
-> useConfigLoader ([]) // array with files or directory with files...
-> useDescriptorLoader ([]) // array with classes or directory with classes...
-> setHosts ([]) //
-> setMiddlewares ([]) // array with middlewares...
-> setPatterns ([]) // available since version 2.11.0
-> build (); use Sunrise Http Router Command RouteListCommand ;
new RouteListCommand ( $ router );可從版本2.13獲得
composer require symfony/event-dispatcher use Sunrise Http Router Event RouteEvent ;
use Symfony Component EventDispatcher EventDispatcher ;
$ eventDispatcher = new EventDispatcher ();
$ eventDispatcher -> addListener (RouteEvent:: NAME , function ( RouteEvent $ event ) {
// gets the matched route:
$ event -> getRoute ();
// gets the current request:
$ event -> getRequest ();
// overrides the current request:
$ event -> setRequest (ServerRequestInterface $ request );
});
$ router -> setEventDispatcher ( $ eventDispatcher );composer test