Problem/Motivation
$request->attributes is currently a dumping ground for:
- Route parameters defined within braces of the route's path pattern (e.g., 'node' if the path pattern is
/node/{node}). - Various other things that should start with "_" in order to not collide with route parameters, whose values either come from the 'defaults' portion of a route definition or from any other code that calls
$request->attributes->set().
For the former, see #2256669: [meta] Finalize module-facing API of getting the matched route name and a matched route argument for a request. This issue is now focused on the latter.
The problems with the latter are:
- It's not friendly DX to access them directly. For example, for
$request->attributes->get('_system_path'), there's no documentation about the existence of '_system_path' as a magic string and what it returns. Even if we created such documentation, it wouldn't be discoverable by IDEs. - It's not clear which magic keys are intended for public use and which are internal. Historically in Drupal, a leading underscore would denote internal use only.
- Before or after 8.0.0 is released, there may be technical reasons to change from storing the data on $request to storing it elsewhere or to computing it dynamically. If contrib modules hardcode their access via $request->attributes, this will lead to BC breaks.
- These problems get compounded if contrib modules follow core practices and add their own magic key/value pairs in $request->attributes without exposing a real API around them.
Here's a grep of HEAD as of May 20, 2014 that orders keys that start with "_" by number of lines of code that access it:
grep -hor --exclude-dir core/vendor "\->attributes->get('_[^,)]*" core | sort | uniq -c | sort -nr
12 ->attributes->get('_system_path'
9 ->attributes->get('_raw_variables'
4 ->attributes->get('_controller'
3 ->attributes->get('_route_params'
2 ->attributes->get('_format'
2 ->attributes->get('_authentication_provider'
1 ->attributes->get('_previous_optional_argument'
1 ->attributes->get('_optional_argument'
1 ->attributes->get('_locale'
1 ->attributes->get('_http_statuscode'
1 ->attributes->get('_hello'
1 ->attributes->get('_form'Proposed resolution
- For _system_path: #2239009: Remove public direct usage of the '_system_path' request attribute
- For _raw_variables: #2256669: [meta] Finalize module-facing API of getting the matched route name and a matched route argument for a request
- For _theme_active: #2238217: Introduce a RouteMatch class incidentally removes most of the usages, possibly other issues in the queue would affect it as well.
- For _entity_type_id: #2238981: Change controllers to receive route parameters in their signature rather than via $request->attributes deals with it, though it's possibly a little weird for a real route parameter to start with an underscore.
- For the others, we should evaluate their usages to make sure they're all internal. For ones that aren't, we should provide a real public API for them.
- Once all usages of all these is strictly internal, document somewhere that that's our rule in general.
Remaining tasks
See above.