Bug: Route Filters Are Ignored When Using Custom Placeholders in Routing
PHP Version
8.3
CodeIgniter4 Version
4.6.3
CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter)
Which operating systems have you tested for this bug?
Windows, Linux
Which server did you use?
apache
Database
No response
What happened?
When defining a custom placeholder in CodeIgniter 4 routing, the routes that use this placeholder do not execute the filters assigned to them. The framework seems to completely skip the filter layer for those routes.
Steps to Reproduce
- Create a custom placeholder in app/Config/Routes.php:
$routes->addPlaceholder('code', '[A-Z]{3}[0-9]+')
- Define a route using this placeholder and apply filters:
$routes->get('test/(:code)', 'TestController::index', ['filter' => 'auth']);
- Access a URL matching the pattern:
/test/ABC123
-
Observe that the auth filter does not run.
-
Check the defined filter from the listed routes using the
php spark routescommand.
| Method | Route | Name | Handler | Before Filters | After Filters
| GET | test/([A-Za-z]+-[A-Za-z0-9]+) | » | \App\Controllers\Test::index/$1 | <unknown> | <unknown>
Additional Notes
- Filters work correctly when using standard placeholders.
- The issue appears only when using custom placeholders created via addPlaceholder().
Expected Output
Filters defined for a route that uses a custom placeholder should run normally, the same way they run with the default placeholders ((:num), (:segment), etc.).
Anything else?
No response
Thank you for reporting. I can only confirm this partially.
For the case you described, following the provided steps, I was able to run filters correctly.
However, the issue still persists with the php spark routes command.
I haven't worked closely with this part of the framework before, but it seems that SampleURIGenerator::samples is used to detect the correct placeholder pattern. We likely need a way to seed SampleURIGenerator with custom samples for new placeholders. Perhaps we could store them in app/Config/Routing.php, though I'm not entirely sure this is the best way to handle this.
Confirm. Global filters are applied. There are no unique routes. I can add the feature to the generator. But I don't like that the user will need to add values. I don't see any other option yet.
It sounds silly. There may be problems if the user overwrites the basic placeholders or examples for them.
// app/Config/Routing.php
/**
* Acceptable values for a custom route placeholder.
*
* After creating a custom placeholder, set one of the acceptable values for it.
* You can skip this step, then the `spark routes` command will not work correctly.
*
* @var array<string, string>
*/
public array $placeholderValues = [
'test' => 'hello01',
'num' => 'slug::word', // replace basic placeholder
];
// system/Commands/Utilities/Routes/SampleURIGenerator.php
final class SampleURIGenerator
{
private readonly RouteCollection $routes;
/**
* Sample URI path for placeholder.
*
* @var array<string, string>
*/
private array $samples = [
'any' => '123/abc',
'segment' => 'abc_123',
'alphanum' => 'abc123',
'num' => '123',
'alpha' => 'abc',
'hash' => 'abc_123',
// after merge input values
// 'test' => 'hello01',
// 'num' => 'slug::word',
];
public function __construct(?RouteCollection $routes = null, array $samples = [])
// or config
public function __construct(?RouteCollection $routes = null, ?Routing $routing = null)
I thought the function wasn't perfect.
For complex route options, the result will be unexpected. It might be worth moving it to routes:check POST /posts/123.
There are many variable parameters to accurately determine the information. The route may have "excerpt" filters - /posts/123 will not give the same for /posts/slug. But for example, he can apply 123 for a placeholder, then the slug filters will be different.