CodeIgniter4 icon indicating copy to clipboard operation
CodeIgniter4 copied to clipboard

Bug: Route Filters Are Ignored When Using Custom Placeholders in Routing

Open frkiergn opened this issue 1 month ago • 3 comments

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

  1. Create a custom placeholder in app/Config/Routes.php:

$routes->addPlaceholder('code', '[A-Z]{3}[0-9]+')

  1. Define a route using this placeholder and apply filters:

$routes->get('test/(:code)', 'TestController::index', ['filter' => 'auth']);

  1. Access a URL matching the pattern:

/test/ABC123

  1. Observe that the auth filter does not run.

  2. Check the defined filter from the listed routes using the php spark routes command.

| 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

frkiergn avatar Nov 19 '25 21:11 frkiergn

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.

michalsn avatar Nov 20 '25 15:11 michalsn

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)

neznaika0 avatar Dec 05 '25 19:12 neznaika0

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.

neznaika0 avatar Dec 06 '25 04:12 neznaika0