Skip to content

Commit b641eb3

Browse files
committed
fix: controller filter attribute docs and improve invalid attribute logging
1 parent 006fc68 commit b641eb3

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
lines changed

system/Router/Router.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -803,8 +803,8 @@ private function processRouteAttributes(): void
803803
if ($instance instanceof RouteAttributeInterface) {
804804
$this->routeAttributes['class'][] = $instance;
805805
}
806-
} catch (Throwable) {
807-
log_message('error', 'Failed to instantiate attribute: ' . $attribute->getName());
806+
} catch (Throwable $e) {
807+
$this->logRouteAttributeInstantiationFailure($attribute->getName(), $this->controller, null, $e);
808808
}
809809
}
810810

@@ -823,14 +823,43 @@ private function processRouteAttributes(): void
823823
if ($instance instanceof RouteAttributeInterface) {
824824
$this->routeAttributes['method'][] = $instance;
825825
}
826-
} catch (Throwable) {
827-
// Skip attributes that fail to instantiate
828-
log_message('error', 'Failed to instantiate attribute: ' . $attribute->getName());
826+
} catch (Throwable $e) {
827+
$this->logRouteAttributeInstantiationFailure($attribute->getName(), $this->controller, $this->method, $e);
829828
}
830829
}
831830
}
832831
}
833832

833+
/**
834+
* Logs an attribute instantiation failure with the resolved route context.
835+
*
836+
* @param string $attributeName Fully qualified attribute class name.
837+
* @param string $controller Resolved controller class name.
838+
* @param string|null $method Resolved controller method name, if applicable.
839+
*/
840+
private function logRouteAttributeInstantiationFailure(
841+
string $attributeName,
842+
string $controller,
843+
?string $method,
844+
Throwable $e,
845+
): void {
846+
$location = $controller;
847+
848+
if ($method !== null && $method !== '') {
849+
$location .= '::' . $method . '()';
850+
}
851+
852+
log_message(
853+
'error',
854+
'Failed to instantiate route attribute "{attribute}" on "{location}": {message}',
855+
[
856+
'attribute' => $attributeName,
857+
'location' => $location,
858+
'message' => $e->getMessage(),
859+
],
860+
);
861+
}
862+
834863
/**
835864
* Execute beforeController() on all route attributes.
836865
* Called by CodeIgniter before controller execution.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Tests\Support\Router\Controllers;
15+
16+
use CodeIgniter\Controller;
17+
use CodeIgniter\HTTP\ResponseInterface;
18+
use CodeIgniter\Router\Attributes\Filter;
19+
20+
class InvalidAttributeController extends Controller
21+
{
22+
#[Filter(by: ['auth', 'csrf'])]
23+
public function invalidMultipleFilters(): ResponseInterface
24+
{
25+
return $this->response->setBody('Invalid attributes');
26+
}
27+
}

tests/system/Router/RouterTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use CodeIgniter\HTTP\Exceptions\RedirectException;
2121
use CodeIgniter\HTTP\IncomingRequest;
2222
use CodeIgniter\HTTP\Method;
23+
use CodeIgniter\Router\Attributes\Filter;
2324
use CodeIgniter\Router\Exceptions\RouterException;
2425
use CodeIgniter\Test\CIUnitTestCase;
2526
use Config\App;
@@ -29,6 +30,7 @@
2930
use PHPUnit\Framework\Attributes\DataProvider;
3031
use PHPUnit\Framework\Attributes\Group;
3132
use Tests\Support\Filters\Customfilter;
33+
use Tests\Support\Router\Controllers\InvalidAttributeController;
3234

3335
/**
3436
* @internal
@@ -1003,4 +1005,27 @@ public function testRoutePlaceholderAnyWithMultipleSegmentsParamTrue(): void
10031005
$this->assertSame('productLookup', $router->methodName());
10041006
$this->assertSame(['123/456'], $router->params());
10051007
}
1008+
1009+
public function testLogsRouteAttributeInstantiationFailureWithContext(): void
1010+
{
1011+
$collection = clone $this->collection;
1012+
$collection->resetRoutes();
1013+
$collection->get(
1014+
'invalid-attribute',
1015+
'Tests\Support\Router\Controllers\InvalidAttributeController::invalidMultipleFilters',
1016+
);
1017+
1018+
$router = new Router($collection, $this->request);
1019+
1020+
$router->handle('invalid-attribute');
1021+
1022+
$this->assertSame(
1023+
'\\' . InvalidAttributeController::class,
1024+
$router->controllerName(),
1025+
);
1026+
$this->assertSame('invalidMultipleFilters', $router->methodName());
1027+
$this->assertSame([], $router->getFilters());
1028+
$this->assertLogContains('error', 'Failed to instantiate route attribute "' . Filter::class . '" on "\Tests\Support\Router\Controllers\InvalidAttributeController::invalidMultipleFilters()":');
1029+
$this->assertLogContains('error', 'must be of type string');
1030+
}
10061031
}

user_guide_src/source/incoming/controller_attributes/003.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ public function api()
1818
{
1919
}
2020

21-
// Multiple filters can be applied
22-
#[Filter(by: ['auth', 'csrf'])]
21+
// Multiple filters can be applied by repeating the attribute
22+
#[Filter(by: 'auth')]
23+
#[Filter(by: 'csrf')]
2324
public function admin()
2425
{
2526
}

0 commit comments

Comments
 (0)