리플렉션 API로 속성 읽기

리플렉션 API로 속성 읽기

이 페이지에서는 Reflection API로 클래스·메서드·함수·매개변수·프로퍼티·클래스 상수에 붙은 속성(attribute)을 읽어내는 방법을 다룹니다. 속성을 선언하는 문법이 아니라 그걸 꺼내 쓰는 쪽의 이야기예요.

출처: Reading Attributes with the Reflection API

본문

클래스, 메서드, 함수, 매개변수, 프로퍼티, 그리고 클래스 상수에서 속성에 접근하려면 Reflection API가 제공하는 getAttributes() 메서드를 사용해요. 이 메서드는 ReflectionAttribute 인스턴스들의 배열을 반환합니다. 이 인스턴스들로 속성의 이름과 인자를 조회할 수 있고, 그 속성이 나타내는 클래스의 인스턴스를 만들 수도 있어요.

반영된(reflected) 속성의 표현을 실제 인스턴스와 분리해 두면 오류 처리에서 더 많은 제어가 가능해져요. 예를 들어 속성 클래스가 없거나, 인자가 잘못 입력되었거나, 값이 빠진 경우를 다루기 좋죠. 속성 클래스의 객체는 ReflectionAttribute::newInstance() 를 호출한 뒤에야 생성되므로, 그 시점에 인자 검증이 일어난다는 걸 보장해 줍니다.

예시를 같이 볼게요.

<?php

#[Attribute]
class MyAttribute
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }
}

#[MyAttribute(value: 1234)]
class Thing
{
}

function dumpAttributeData($reflection) {
    $attributes = $reflection->getAttributes();

    foreach ($attributes as $attribute) {
       var_dump($attribute->getName());
       var_dump($attribute->getArguments());
       var_dump($attribute->newInstance());
    }
}

dumpAttributeData(new ReflectionClass(Thing::class));
string(11) "MyAttribute"
array(1) {
  ["value"]=>
  int(1234)
}
object(MyAttribute)#3 (1) {
  ["value"]=>
  int(1234)
}

리플렉션 인스턴스의 모든 속성을 훑는 대신, 특정 속성 클래스에 속한 것만 골라낼 수도 있어요. 그럴 땐 속성 클래스 이름을 인자로 넘겨주면 됩니다.

<?php
#[Attribute]
class MyAttribute
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }
}

#[MyAttribute(value: 1234)]
class Thing
{
}

function dumpMyAttributeData($reflection) {
    $attributes = $reflection->getAttributes(MyAttribute::class);

    foreach ($attributes as $attribute) {
       var_dump($attribute->getName());
       var_dump($attribute->getArguments());
       var_dump($attribute->newInstance());
    }
}

dumpMyAttributeData(new ReflectionClass(Thing::class));

더 알아보기