Conversation
6f471ae to
a8834d2
Compare
a8834d2 to
77ca3ef
Compare
I have forgotten, that it would break our code style rules - therefore I am fine having the PascalCase |
LordSimal
left a comment
There was a problem hiding this comment.
Love so see this finalized and working 🥳
…rs for extra guarding and attribute based automatic route connecting
This comment was marked as outdated.
This comment was marked as outdated.
|
@josbeir In your usage example the |
Updated, but it actually works like you'd expect. If you put it in a scope then all discovered attributes from a resolver config (which is the only optional argument of So yes for root attributes it can be added inside the '/' scope or outside, they will all start at root level. The example illustrated that it also work likes that (handy feature actually 😎) |
Oh, so if I do |
No, they just will all be connected to the /admin scope. // routes.php
$routes->scope('/admin', function(RouteBuilder $routes) {
$routes->attributes();
});
// A controller
#[Scope('/articles')]
class ArticlesController extends AppController {
#[Get('/list')]
public function index() {
}
}will result in Basically the resolver holds the list of discovered route attributes. Then these routes are connected to the scope where So if a resolver configuration is there that targets a specific path/pattern then that config could be used to connect a specific subset of routes to a scope. Not something we should explicitly promote but it is a use case that could be handy. |
|
@markstory @dereuromark thoughts? |
7df7506 to
a839d54
Compare
cbe1660 to
ae4c935
Compare
|
Minor Observations: Copilot's point about duplicate regex - The extractPathPlaceholders() duplicating PLACEHOLDER_REGEX from the Route class is a valid concern for maintainability. Questions I'd have:
|
I believe it would be non-deterministic and whichever gets loaded first will take precedence.
The docblock of
@josbeir I don't see tests using the |
Added an integration test to confirm registration is working properly trough the resolver, it was already synthetically tested. Below a little example of how this works (php 8.5+ only): <?php
#[Scope(path: '/api')]
#[Middleware(static function (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$response = $handler->handle($request);
return $response->withHeader('X-Api-Version', '2.0');
})]
class ArticlesController extends AppController
{
#[Get('/articles', 'articles:index')]
#[Middleware(static function (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
// inline rate-limit logic
return $handler->handle($request);
})]
public function index(): void
{
}
} |
|
docs PR: cakephp/docs#8257 |
Using route scoped middewares is a 2 step process, first you need to register the middleware ( So when using the Edit: I see now the docs clarify the above. |
Would be nice if it would be possible to load a file only for PHP 8.5+, so that we don't have an untested feature. |
I'll see what I can whip up, but it is already tested, just not coming from the registry directly |
| * | ||
| * @param array<string> $extensions File extensions. | ||
| */ | ||
| public function __construct(public array $extensions) |
There was a problem hiding this comment.
| public function __construct(public array $extensions) | |
| public function __construct(public array|string $extensions) |
This would make it match the argument type for RouteBuilder::setExtensions()
Refs #19228
Summary
Implements the attribute-routing RFC from #19228 by introducing route attributes, wiring attribute discovery/connection into routing, and aligning controller action argument binding for named/positional route params.
This also extends
AttributeResolvermetadata so routing can make controller-instantiability and action-eligibility decisions without reflection in the connector layer.What changed
Route, HTTP method shortcuts (Get,Post,Put,Patch,Delete,Options,Head)Scope,Prefix,RouteClass,Middleware,Extensions,ResourceAttributeRouteConnectorto:_argsByNamemetadata frompass/placeholdersRouteBuilder::attributes()integration to connect resolver-discovered routes.ControllerFactoryto support_argsByNamemapping while preserving existing positional/named pass behavior.AttributeResolver updates (and why)
AttributeTargetmetadata with:declaringClassType(class/interface/trait/enum)isDeclaringClassAbstractmethodVisibility(public/protected/private, for method-related targets)isInstantiableDeclaringType()andisPublicMethodTarget()MethodVisibilityenum.Parserto populate class-type/abstractness metadata once per class and method visibility once per method, then propagate into method/parameter targets.Why this was needed:
Forward-looking note
methodVisibilitymetadata also opens a path for future “auto-scoped routes” mode, where all public controller methods inside a scope could be connected automatically without relying on fallback routing.Usage examples (after setting up AttributeResolver)