컨트롤러 속성

PHP 속성은 컨트롤러 클래스와 메서드에 필터와 기타 메타데이터를 정의하는 데 사용할 수 있습니다. 이렇게 하면 설정이 영향을 받는 코드와 가까이 유지되며, 특정 컨트롤러나 메서드에 어떤 필터가 적용되는지 한눈에 더 쉽게 파악할 수 있습니다. 이는 자동 라우팅을 포함한 모든 라우팅 방식에서 동작하며, 더 견고한 라우트 선언과 자동 라우팅 사이의 기능 차이를 거의 없애 줍니다.

시작하기

컨트롤러 속성은 클래스 전체 또는 특정 메서드에 적용할 수 있습니다. 다음 예제는 컨트롤러 클래스에 Filters 속성을 적용하는 방법을 보여줍니다:

<?php

namespace App\Controllers;

use CodeIgniter\Router\Attributes\Filter;

#[Filter(by: 'auth')]
class AdminController extends BaseController
{
    public function index()
    {
        return view('welcome_message');
    }
}

이 예제에서는 Auth 필터가 AdminController의 모든 메서드에 적용됩니다.

컨트롤러의 특정 메서드에만 Filters 속성을 적용할 수도 있습니다. 이렇게 하면 특정 메서드에만 필터를 적용하고 다른 메서드는 영향을 받지 않게 할 수 있습니다. 예제는 다음과 같습니다:

<?php

namespace App\Controllers;

use CodeIgniter\Router\Attributes\Filter;

#[Filter(by: 'group', having: ['admin', 'superadmin'])]
class AdminController extends BaseController
{
    #[Filter(by: 'permission', having: ['users.manage'])]
    public function users()
    {
        // Will have 'group' filter with ['admin', 'superadmin']
        // and 'permission' filter with ['users.manage']
    }
}

클래스 수준과 메서드 수준의 속성은 함께 작동하여 컨트롤러 수준에서 라우트를 유연하게 관리할 수 있게 합니다.

속성 비활성화

애플리케이션에서 속성을 사용하지 않을 것이 확실하다면 app/Config/Routing.php 파일의 $useControllerAttributes 속성을 false로 설정하여 기능을 비활성화할 수 있습니다.

제공되는 속성

필터

Filters 속성을 사용하면 컨트롤러 클래스나 메서드에 적용할 하나 이상의 필터를 지정할 수 있습니다. 컨트롤러 작업 전 또는 후에 실행할 필터를 지정할 수 있으며, 필터에 매개변수를 전달할 수도 있습니다. Filters 속성 사용 예제는 다음과 같습니다:

<?php

namespace App\Controllers;

use CodeIgniter\Router\Attributes\Filter;

class HomeController extends BaseController
{
    // Apply the filter by it's alias name
    #[Filter(by: 'csrf')]
    public function index()
    {
    }

    // Apply a filter with arguments
    #[Filter(by: 'throttle', having: ['60', '1'])]
    public function api()
    {
    }

    // Multiple filters can be applied by repeating the attribute
    #[Filter(by: 'auth')]
    #[Filter(by: 'csrf')]
    public function admin()
    {
    }
}

참고

필터가 속성과 필터 설정 파일 양쪽에서 적용되면 둘 다 적용되지만, 예상하지 못한 결과가 생길 수 있습니다.

참고

필터에 적용되는 모든 매개변수는 문자열로 변환된다는 점을 기억하세요. 이 동작은 필터에만 영향을 줍니다.

제한

Restrict 속성을 사용하면 도메인, 서브도메인 또는 애플리케이션이 실행되는 환경을 기준으로 클래스나 메서드에 대한 접근을 제한할 수 있습니다. Restrict 속성 사용 예제는 다음과 같습니다:

<?php

namespace App\Controllers;

use CodeIgniter\Router\Attributes\Restrict;

// Restrict access by environment
#[Restrict(environment: ['development', '!production'])]
class HomeController extends BaseController
{
    // Restrict access by hostname
    #[Restrict(hostname: 'localhost')]
    public function index()
    {
    }

    // Multiple allowed hosts
    #[Restrict(hostname: ['localhost', '127.0.0.1', 'dev.example.com'])]
    public function devOnly()
    {
    }

    // Restrict to subdomain, e.g. admin.example.com
    #[Restrict(subdomain: 'admin')]
    public function deleteItem($id)
    {
    }
}

캐시

Cache 속성을 사용하면 컨트롤러 메서드의 출력을 지정한 시간 동안 캐시할 수 있습니다. 초 단위 지속 시간을 지정할 수 있고, 선택적으로 캐시 키도 지정할 수 있습니다. Cache 속성 사용 예제는 다음과 같습니다:

<?php

namespace App\Controllers;

use CodeIgniter\Router\Attributes\Cache;

class HomeController extends BaseController
{
    // Cache this method's response for 2 hours
    #[Cache(for: 2 * HOUR)]
    public function index()
    {
        return view('welcome_message');
    }

    // Custom cache key
    #[Cache(for: 10 * MINUTE, key: 'custom_cache_key')]
    public function custom()
    {
        return 'This response is cached with a custom key for 10 minutes.';
    }
}

사용자 정의 속성

컨트롤러와 메서드에 메타데이터나 동작을 추가하기 위해 직접 사용자 정의 속성을 만들 수도 있습니다. 사용자 정의 속성은 CodeIgniter\Router\Attributes\RouteAttributeInterface 인터페이스를 구현해야 합니다. 다음은 응답에 사용자 정의 헤더를 추가하는 사용자 정의 속성의 예제입니다:

<?php

namespace App\Attributes;

use Attribute;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Router\Attributes\RouteAttributeInterface;

/**
 * Custom Header Attribute
 *
 * Adds custom headers to the response. This is useful for:
 * - Adding security headers
 * - Setting API version information
 * - Adding custom metadata to responses
 */
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class AddHeader implements RouteAttributeInterface
{
    /**
     * @param string $name  The header name
     * @param string $value The header value
     */
    public function __construct(
        private readonly string $name,
        private readonly string $value,
    ) {
    }

    /**
     * Called before the controller method executes.
     * Return null to continue to the controller.
     */
    public function before(RequestInterface $request): RequestInterface|ResponseInterface|null
    {
        // We don't need to do anything before the controller runs
        return null;
    }

    /**
     * Called after the controller method executes.
     * Add the custom header to the response.
     */
    public function after(RequestInterface $request, ResponseInterface $response): ?ResponseInterface
    {
        $response->setHeader($this->name, $this->value);

        return $response;
    }
}

그다음에는 이 사용자 정의 속성을 내장 속성과 마찬가지로 컨트롤러 클래스나 메서드에 적용할 수 있습니다:

<?php

namespace App\Controllers;

use App\Attributes\AddHeader;
use CodeIgniter\Controller;
use CodeIgniter\Router\Attributes\Cache;

class Api extends Controller
{
    /**
     * Add a single custom header
     */
    #[AddHeader('X-API-Version', '2.0')]
    public function userInfo()
    {
        return $this->response->setJSON([
            'name'  => 'John Doe',
            'email' => 'john@example.com',
        ]);
    }

    /**
     * Add multiple custom headers using the IS_REPEATABLE attribute option.
     * Each AddHeader attribute will be executed in order.
     */
    #[AddHeader('X-API-Version', '2.0')]
    #[AddHeader('X-Rate-Limit', '100')]
    #[AddHeader('X-Content-Source', 'cache')]
    public function statistics()
    {
        return $this->response->setJSON([
            'users' => 1500,
            'posts' => 3200,
        ]);
    }

    /**
     * Combine custom attributes with built-in attributes.
     * The Cache attribute will cache the response,
     * and AddHeader will add the custom header.
     */
    #[AddHeader('X-Powered-By', 'My Custom API')]
    #[Cache(for: 3600)]
    public function dashboard()
    {
        return $this->response->setJSON([
            'status' => 'operational',
            'uptime' => '99.9%',
        ]);
    }
}