Skip to content

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

Closed

Description

@frkiergn

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

Activity

  1. added
    bugVerified issues on the current code behavior or pull requests that will fix them
    on Nov 19, 2025
  2. michalsn commented on Nov 20, 2025

    @michalsn
    Member

    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.

  3. neznaika0 commented on Dec 5, 2025

    @neznaika0
    Contributor

    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)
  4. neznaika0 commented on Dec 6, 2025

    @neznaika0
    Contributor

    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.

  5. added 2 commits that reference this issue on May 18, 2026
    31f6444
    fc75029
  6. paulbalandan commented on Jun 5, 2026

    @paulbalandan
    Member

    Fixed in #10263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugVerified issues on the current code behavior or pull requests that will fix them

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions