• 목록
  • 아래로
  • 위로
  • 0
  • 네모
  • 조회 수 61

from. https://velog.io/@qroffle/PHP-%EC%86%8C%EC%8B%9D-Attribute

 

post-thumbnail

 

PHP8.0에 Attribute라는 새로운 친구가 나타났습니다.
PHP8이 출시된지 한참 지났는데, 이제와서... 라는 느낌이 들기는 합니다만!
이상하게 국내에는 이 친구를 소개하는 글이 없더라구요.

 


 

Attribute?

 

Attribute는 클래스, 익명 클래스, 클래스 변수, 클래스 메서드, 함수, 클로져, 상수에 추가할 수 있는 메타데이터 요소입니다.

기존의 DocBlock 주석이 제일 비슷한 용법이 될 수 있겠네요.

/**
 * @param string $person
 */
function cute(string $person){}

이런 주석은 @param 이라는 일종의 암묵적인 룰으로 구성되어 있지요.
(엄밀히 따지면 암묵적이지는 않지만요.)

 


이런 만화책도 있었군요...?

아무튼, 저 코드는 실제로 실행되지는 않지만 PHP에서는 Reflection API 라는 것을 통해 주석을 검색할 수 있도록 하고 있습니다.

 

/**
 * @param string $person
 */
function cute(string $person){}

$reflection = new ReflectionFunction('cute');
$docs = $reflection->getDocComment();
var_dump($docs);

이러한 기능을 아주 알뜰살뜰히 챙긴 라이브러리가 있지요.
이름하야 Doctrine! https://www.doctrine-project.org/

 

이러한 짭 Annotation 을 활용한 방식은 역시 관리하기 힘들고, 잘 보이지도 않고, IDE가 이쁘게 출력해 주지도 않습니다.
DocBlock 문법을 따르는 암묵적인 룰은 있지만, 말 그대로 암묵적인 룰이니까요.

 

그래서 PHP8에는 새로운 방식이 추가되었습니다.
Attribute는 이런 정보를 좀 더 펀쿨섹한 방법으로 구현하고 있습니다.

 

// DocBlock 을 사용하는 방식
class HolymolyController extends AbstractController
{
    /**
     * @Route('/holymoly')
     */
    public function index(){}
}
// Attribute 를 사용하는 방식
class HolymolyController extends AbstractController
{
    #[Route('/holymoly')]
    public function index(){}
}

 

 


 

 

사용법

 

Attribute 적용

#[LoremAttr()]
class Ipsum
{
    #[DolorAttr('Sit')]
    private string $amet;
    
    #[LoremAttr(), DolorAttr]
    public function consectetur()
    {
    }
}

// Attribute 클래스 선언
#[Attribute]
class LoremAttr
{
    public function __construct(){}
}

#[Attribute]
class DolorAttr
{
    public function __construct(?string $param1 = null){}
}

생겨난지 얼마 되지 않은 친구라 그런지, PSR 코드 스타일이 아직은 존재하지 않습니다.
개인적으로는 아래의 스타일을 따라 사용하고 있습니다.

 

  • Attribute 는 항상 선언부 바로 위에 (DocBlock 밑에)
  • #[ 와 ] 사이에 공백을 남기지 않음
  • 하나의 #[] 블럭 안에 하나의 Attribute 만 선언
  • 인자를 전달하지 않아도 되는 Attribute 라도 뒤에 () 를 추가

 


 

Attribute 선언

 

Attribute는 클래스로 선언됩니다. Attribute 클래스의 유효성은 Reflection API 를 통해 정보를 가져올때에만 검사되고, 선언 그 자체로 유효성을 검증받지는 않습니다.

클래스에는 표준 PHP 클래스인 \Attribute 를 Attribute 로 추가해 주어야 합니다.
(\Attribute 는 final 으로 선언되어 있습니다. 확장이 불가능해요.)

#[Attribute]
class LoremAttr
{
}

기본적으로 선언된 Attribute 는 Attribute 를 허용하는 모든 요소에서 사용할 수 있습니다.
그러니까, 클래스, 변수, 함수 등등에서요.

특정 요소에만 적용을 허용하고 싶다면, 아래 방법을 사용할 수 있습니다.

#[Attribute(Attribute::TARGET_CLASS)]
class LoremAttr
{
}

허용되는 인자는 아래와 같습니다.

  • Attribute::TARGET_ALL (기본값)
  • Attribute::TARGET_CLASS (클래스)
  • Attribute::TARGET_METHOD (클래스 메서드)
  • Attribute::TARGET_PROPERTY (클래스 멤버변수)
  • Attribute::TARGET_CLASS_CONSTANT (클래스 상수)
  • Attribute::TARGET_FUNCTION (함수)
  • Attribute::TARGET_PARAMETER (인자)

 


 

Attribute 획득

 

Attribute 의 정보는 Reflection API 를 통해 얻어올 수 있습니다.
바로 getAttributes() 메서드를 사용해서요.

모든 Reflection* 클래스에는 getAttributes() 라는 메서드가 추가되었으며,
해당 메서드는 ReflectionAttribute 라는 객체 배열을 반환합니다.

$reflector = new ReflectionClass(Ipsum::class);
$attrs = $reflector->getAttributes();

혹, 특정 Attribute 클래스만을 획득하고 싶다면, getAttributes() 에 인자로 전달해주면 됩니다.

$attrs = $reflector->getAttributes(LoremAttr::class);

ReflectionAttribute 에는 다음과 같은 메서드가 존재합니다.

  • getName(): string
  • getArguments(): array
  • newInstance(): object

 

newInstance()

 

newInstance() 메서드는 Attribute 클래스의 인자를 반환합니다.
적용된 Attribute 에 인자가 있다면 해당 인자를 __construct() 로 전달해주는건 당연한 일이구요.

아래 코드와 같이 사용할 수 있습니다.

#[LoremAttr('CuteQroffle')]
class Ipsum {}

#[Attribute]
class LoremAttr
{
    private string $message;
    
    public function __construct(string $message)
    {
        $this->message = $message;
    }
}

$reflector = new ReflectionClass(Ipsum::class);
$attrs = $reflector->getAttributes();
foreach($attrs as $attr)
{
	var_dump($attr->newInstance());
}

SO EASY!

 

 

 


 

 

 

기타

 

Doctrine ORM 에서는 이미 Annotation 대신 Attribute 를 사용하여 ORM 을 구성할 수 있게 되었습니다.
https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/attributes-reference.html

 

Laravel 에서 Attribute 를 사용하여 라우팅할 수 있도록 하는 라이브러리도 있구요.
개인적으로 제일 마음에 드는 활용입니다. 퍼포먼스 문제가 있느냐 마느냐는 둘째치구요.
https://github.com/spatie/laravel-route-attributes

 

PHPStorm 에서는 프로젝트 언어를 PHP8 이상으로 설정할 경우, 몇가지 IDE용 Attribute를 추가적으로 제공합니다. 대표적으로 Deprecated 가 있지요.
다만, PHP8을 적용한 프로젝트들은 새로 작성하는 프로젝트가 대부분이라 제 입장에선 크게 와닿지 않네요.

Ruwaku님 포함 2명이 추천

추천인 2

작성자
네모 70 Lv. (34%) 395850/403280EXP

인스타그램 : http://instg.me/nemo_9l

댓글 0

권한이 없습니다.