정보실

웹학교

정보실

php PHP 7.4의 타입 속성에 대한 종합 안내서

본문

PHP 7.4의 타입 속성 


PHP 7.4는 마침내 타입 속성을 제공합니다. 이것은 내가 기대했던 기능이며, 유형이 지정된 속성에 대한 지원을 추가하기 위해 기존 프로젝트에서 약간의 품질 시간을 소비하고 있습니다.


https://php.watch/versions/7.4/typed-properties 


유형이 지정된 속성을 사용하면 모든 클래스 속성에 대한 유형을 설정할 수 있습니다. 유형이 설정되면 PHP 엔진은 다른 사람이 클래스 속성에 다른 유형을 설정하지 못하게 합니다.


class Example {
  public string $name;
  public DateTime $birthday;
}

위의 스니펫은 Example :: $birthday 속성이 항상 DateTime 개체가 되도록 합니다. PHP 7.4 이전에는 이러한 종류의 엄격한 데이터 패턴이 데이터 무결성을 강화하기 위해 setBirthDate (DateTime $birthdate) : void and getBirthDate() : \ DateTime 메소드를 가져야 했습니다.


지원되는 Type 유형 


클래스 속성에 지원되는 유형

  • Scalar types: int, string, bool, and float.
  • Compound types: array, iterable and object.
  • Any class or interface name (such as DateTime, Foo\Bar) and stdClass.
  • References to parent and own objects: self and parent.

클래스 속성에 지원되지 않는 유형

  • void: Having a void property wouldn't make sense.
  • callable: Not supported because its behavior is unpredictable. Take a look at consistent callables RFC for more background. This basically becomes troublesome when callables can be declared with array syntax, e.g. as [$this, 'buildForm'].

초기화되지 않은 상태 


이것은 대부분의 모발이 발생할 수 있는 곳입니다. PHP 7.4 유형의 속성을 사용하면 클래스 속성은 초기화되지 않은 상태입니다. 이것은 단순히 속성이 아직 초기화되지 않았음을 의미합니다. 이것은 null과 동일하지 않습니다.


선언 된 유형이 없으면 속성은 초기화되지 않은 값으로 null을 갖습니다.


class Example {
  public $name;
}

$foo = new Example();
var_dump($foo->name === null); // true


형식이 선언되면 모든 속성이 초기화되지 않은 상태가 됩니다. 명시적인 값을 할당하기 전에 클래스 속성에 액세스 할 수 없습니다.


class Example {
  public string $name;
}

$foo = new Example();
var_dump($foo->name === null);


이 스니펫에서 $ name 특성은 초기화되지 않았습니다. 이것은 null과 같지 않으며 위의 스니펫은 오류를 발생시킵니다.


Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...


초기화되지 않은 상태 확인 


isset ($ foo-> name)을 사용하여 클래스 속성이 초기화되지 않았는지 확인할 수 있습니다. 이 값은 null과 같지 않으므로 $ foo-> name === null을 사용하여 속성이 초기화되지 않았는지 확인할 수 없습니다.


속성을 초기화되지 않은 상태로 재설정 


속성을 초기화되지 않은 상태로 다시 설정하려면 unset ($ foo-> name)을 사용하십시오. 설정이 해제되면 값을 지정하지 않고 속성에 액세스 하려고 하면 동일한 형식화 된 속성이 throw됩니다. 초기화하기 전에 액세스해서는 안됩니다 ... 오류.


널 입력 가능 유형 


PHP 7.1의 nullable 타입과 비슷하게 프로퍼티 타입도 nullable로 표시 될 수 있습니다. 속성을 null로 표시하려면 해당 유형 앞에 물음표를 붙이십시오 (예 :? string).


class Example {
  public ?string $name;
}

$foo = new Example();
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid

속성이 nullable로 표시 되더라도 초기화되지 않은 값은 null이 아닙니다. 예를 들어 아래 스니펫은 여전히 ​​오류를 발생시킵니다.


class Example {
  public ?string $name;
}

$foo = new Example();
var_dump($foo->name);
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization

이것은 작업하기가 번거로울 수 있지만 클래스 속성이 항상 해당 유형임을 확신 할 수 있는 훌륭한 기능을 제공합니다. 값이 초기화되지 않으면 PHP는 형식화 되지 않은 속성과 마찬가지로 null을 반환하는 대신 오류를 포기하고 throw합니다.


엄격한 유형 


클래스 속성은 파일의 PHP 블록 상단에 선언 (strict_types = 1)을 사용하여 엄격한 형식 선언을 지원합니다. 엄격한 유형이 없으면 PHP는 값을 속성 유형으로 캐스팅 합니다.


class Example {
  public string $name;
}

$foo = new Example();
$foo->name = 420;
var_dump($foo->name);
// string(3) "420"

문자열 속성에 정수를 설정하는 방법과 var_dump () 호출은 문자열로 "420"을 반환합니다. 값을 할당 할 때 엔진은 값을 선언 된 유형으로 캐스팅 합니다.


형식 저글링 문제를 최소화하고 형식화 된 속성의 모든 이점을 활용하려면 선언 (strict_types = 1)으로 클래스를 테스트하는 것이 좋습니다. PHP가 당신을 위해 타입으로 캐스팅 할 때 도움이 될 때 간과하기 쉽지만 이것은 다운 스트림 버그의 근본이 될 수 있습니다. 금요일 저녁 6시 28 분 오후에만 발생하는 버그보다 즉시 나타나는 오류를 디버그 하는 것이 더 쉽습니다 (DST가 적용되는 경우에만).


정적 속성 및 참조 


정적 속성에는 형식도 선언 할 수 있습니다. 이것은 명백한 세부 사항처럼 보이지만 이전 유형의 속성 제안에는 정적 속성이 포함되지 않았습니다. PHP 7.4에서는 정적 속성에 대한 유형도 선언 할 수 있습니다.


또한 유형이 지정된 속성에 대한 참조를 반환 할 수 있으며 해당 유형은 계속 적용됩니다.


class Example {
  public string $name;
}

$foo = new Example();
$foo->name = 'Apple';
$bar =& $foo->name;
$bar = []; // Not allowed

오류가 발생합니다.


Fatal error: Uncaught TypeError: Cannot assign ... to reference held by property Example::$name of type ... in ...

생성자 및 속성 선언의 기본값 


역사적인 이유로, PHP에서는 타입이 널 입력 가능하지 않더라도 선언에서 함수 인수에 대한 기본값을 설정할 수 있습니다.


class Example {
  public function __construct(string $name = null) {
      var_dump($name);
  }
}

$foo = new Example();
// NULL


생성자에서 $name 인수가 널 입력 가능하지 않음을 명시 적으로 표시하지만 PHP는 널을 기본값으로 허용합니다. 이 동작은 null 기본값에만 적용됩니다. 이것이 의미 상 유효하지는 않지만,이 동작은 과거 및 구현상의 이유로 허용됩니다.


유형이 지정된 속성으로는 허용되지 않습니다.

class Example {
    private string $name = null;
}

$foo = new Example();
// NULL

즉시 오류가 발생합니다.


Fatal error: Default value for property of type ... may not be null. Use the nullable type ?... to allow null default value in ...


유형 차이 


PHP 7.4에는 반환 유형 차이가 있으므로 자식 클래스가 더 구체적인 인스턴스를 반환 할 수 있습니다. 속성 유형에는 아직 지원되지 않습니다. 예를 들면 다음과 같습니다.


class A {}
class B extends A {}

class Fruits {
    public B $foo;
}
class Banana extends Fruits {
    public A $foo;
}

위의 코드는 작동하지 않습니다. B는 A 클래스의 하위 집합이지만 Banana :: $ foo의 형식 선언을 변경하는 것은 허용되지 않습니다. 여전히 A 인스턴스를 Banana :: $ foo에 할당 할 수 있습니다. 이를 공분산이라고 하며 이제 반환 유형에 대해 지원됩니다. 위를 시도하면 다음과 같은 오류가 발생합니다.


Fatal error: Type of Banana::$foo must be B (as in class Fruits) in W:\localhost\test\test.php on line 11

다음 코드는 여전히 유효합니다.


class A {}
class B extends A {}

class Fruits {
    public A $foo;
}
class Banana extends Fruits {
    public A $foo;
}

$banana = new Banana();
$banana->foo = new B();


Fruits :: $foo 및 Banana :: $foo의 속성 선언이 A 인 방법에 주목하지만 인스턴스 B를 할당합니다.


요약:

  • You cannot substitute a child class for the property.
  • You cannot add types to child classes if the parent does not have types enforced.
  • You cannot mark a non-nullable type as nullable in a child class.
  • You cannot mark a nullable type as non-nullable in a child class.

이것을 시각화 하려면 다음 상속 체인을 살펴보십시오. 다음 중 어느 것도 허용되지 않습니다.


class A {}
class B extends A{}

class Fruits {
    public $no_type;
    public A $strict_type;
    public ?string $nullable;
    public string $non_nullable;
}
class Banana extends Fruits {
    public A $no_type; // Not allowed to add types in a subclass.
    public $strict_type; // Not allowed to remove type in a childclass.
    public string $nullable; // Not allowed to make non-nullable
    public ?string $non_nullable; // Not allowed to make nullable
}

위와 같은 오류는 동시에 발생하지 않습니다.


Fatal error: Type of Banana::$no_type must not be defined (as in class Fruits) in ... on line ...
Fatal error: Type of Banana::$strict_type must be A (as in class Fruits) in ... on line 17
Fatal error: Type of Banana::$nullable must be ?string (as in class Fruits) in ... on line 17
Fatal error: Type of Banana::$non_nullable must be string (as in class Fruits) in ... on line 17

이전 버전과의 호환성 


속성 유형 선언은 선택 사항이며 모든 기존 코드가 작동합니다. 기존 코드베이스를 유형이 지정된 속성으로 업그레이드하려는 경우 초기화되지 않은 상태 및 규칙이 다소 엄격하게 적용되는 상속을 주시하십시오. 또한 속성 유형은 함수 / 메소드 인수에 null 값을 허용하는 레거시 동작을 수행하지 않으므로 놀랍습니다.


마지막 생각들 


속성 유형은 개인적으로 흥분된 기능이며, 이제 여기에 왔으므로 기존 개인 프로젝트에 속성 유형을 추가하는 데 시간을 보냈습니다. PHPStorm 2019.3은 모든 PHP 7.4 기능을 지원하며 속성 docblock 주석 또는 생성자에서 수집 할 수 있는 경우 속성 유형을 추가하는 빠른 수정 사항이 있습니다. 테스트 범위가 100 % 인 프로젝트에서도 여전히 몇 가지 버그가 발견되었지만 속성 유형으로 인해 앞뒤에 있습니다!


오픈 소스 프로젝트는 PHP 7.4를 최소 버전으로 요구하는 데 다소 시간이 걸릴 수 있지만 개인 프로젝트에서 PHP 7.4를 사용하는 것을 막지는 못합니다.



  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 28회 ]  작성일19-12-14 11:02

웹학교