분류 php

PHP 8의 새로운 기능

컨텐츠 정보

  • 조회 349 (작성일 )

본문

PHP 8이 출시되었습니다! 2020 년 11 월 26 일에 출시되었습니다. 여기에서 다운로드 할 수 있습니다. 새로운 주요 버전이므로 몇 가지 주요 변경 사항과 많은 새로운 기능 및 성능 개선 사항을 도입 할 것입니다.


주요 변경 사항으로 인해 PHP 8에서 실행되도록 코드를 약간 변경해야 할 가능성이 높습니다. 그래도 최신 릴리스를 최신 상태로 유지했다면 대부분의 주요 변경 사항이 이전에 7. * 버전에서 사용되지 않기 때문에 업그레이드가 너무 어렵지 않을 것입니다. 걱정하지 마세요. 이러한 모든 지원 중단이 이 게시물에 나와 있습니다.


주요 변경 사항 외에도 PHP 8은 JIT 컴파일러, 공용체 유형, 속성 등과 같은 멋진 새 기능 세트를 제공합니다.


새로운 기능 


모든 새로운 기능부터 시작해 보겠습니다. 꽤 많은 목록입니다!


Union types 


PHP의 동적 유형 특성을 고려할 때 공용체 유형이 유용한 경우가 많이 있습니다. 공용체 유형은 둘 중 하나를 사용할 수 있음을 나타내는 두 개 이상의 유형 모음입니다.


public function foo(Foo|Bar $input): int|float; 


void는 "반환 값이 전혀 없음"을 나타 내기 때문에 공용체 유형의 일부가 될 수 없습니다. 또한 nullable 공용체는 null을 사용하거나 기존? 표기법:


public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void; 


JIT 


JIT (just in time) 컴파일러는 웹 요청의 컨텍스트 내에서 항상 그런 것은 아니지만 상당한 성능 향상을 약속합니다. 나는 실제 웹 애플리케이션에 대한 내 자신의 벤치 마크를 수행했으며 JIT가 그러한 종류의 PHP 프로젝트에서 그다지 큰 차이를 만들지 않는 것 같습니다.


JIT가 PHP에서 무엇을 할 수 있는지에 대해 더 알고 싶다면 여기에서 내가 쓴 또 다른 게시물을 읽을 수 있습니다.


The nullsafe operator 


null 병합 연산자에 익숙하다면 그 단점에 이미 익숙한 것입니다. 메서드 호출에서는 작동하지 않습니다. 대신 중간 검사가 필요하거나 일부 프레임 워크에서 제공하는 선택적 도우미에 의존합니다.


$startDate = $booking->getStartDate(); $dateAsString = $startDate ? $startDate->asDateTimeString() : null; 


nullsafe 연산자를 추가하여 이제 메서드에서 null 병합과 같은 동작을 할 수 있습니다!


$dateAsString = $booking->getStartDate()?->asDateTimeString(); 



여기에서 nullsafe 연산자에 대한 모든 것을 읽을 수 있습니다.


Named arguments 


명명 된 인수를 사용하면 값 이름을 지정하여 값을 함수에 전달할 수 있으므로 순서를 고려할 필요가 없으며 선택적 매개 변수를 건너 뛸 수도 있습니다!


function foo(string $a, string $b, ?string $c = null, ?string $d = null) { /* … */ } foo( b: 'value b', a: 'value a', d: 'value d', ); 


이 게시물에서 이에 대해 자세히 읽을 수 있습니다.


Attributes 


일반적으로 다른 언어에서 주석으로 알려진 속성은 docblock을 구문 분석하지 않고도 메타 데이터를 클래스에 추가하는 방법을 제공합니다.


간략히 살펴보면 RFC에서 가져온 속성의 예는 다음과 같습니다.


use App\Attributes\ExampleAttribute; #[ExampleAttribute] class Foo { #[ExampleAttribute] public const FOO = 'foo'; #[ExampleAttribute] public $x; #[ExampleAttribute] public function foo(#[ExampleAttribute] $bar) { } } 


#[Attribute] class ExampleAttribute { public $value; public function __construct($value) { $this->value = $value; } } 


이 기본 속성은 원래 RFC에서 PhpAttribute라고 불렸지만 나중에 다른 RFC로 변경되었습니다. 속성이 작동하는 방식과 속성을 직접 구축 할 수 있는 방법에 대해 자세히 알아보고 싶다면; 이 블로그에서 속성에 대해 자세히 읽을 수 있습니다.

 

Match expression 


이를 switch 표현식의 큰 형제라고 부를 수 있습니다. match는 값을 반환 할 수 있고, break 문이 필요하지 않으며, 조건을 결합 할 수 있으며, 엄격한 유형 비교를 사용하고 어떤 유형 강제도 수행하지 않습니다.


다음과 같이 보입니다.


$result = match($input) { 0 => "hello", '1', '2', '3' => "world", }; 


여기에서 일치 식에 대해 자세히 읽을 수 있습니다.


Constructor property promotion 


이 RFC는 가치 객체 또는 데이터 전송 객체를 생성하기 위해 구문 설탕을 추가합니다. 클래스 속성과 생성자를 지정하는 대신 PHP는 이제 이를 하나로 결합 할 수 있습니다.


이렇게 하는 대신 :


class Money { public Currency $currency; public int $amount; public function __construct( Currency $currency, int $amount, ) { $this->currency = $currency; $this->amount = $amount; } } 


이제 다음을 수행 할 수 있습니다.


class Money { public function __construct( public Currency $currency, public int $amount, ) {} } 


속성 홍보에 대해 더 많은 정보가 있으며,이 전용 게시물에서 이에 대해 읽을 수 있습니다.


New static return type 


이미 self를 반환 할 수 있었지만 static은 PHP 8까지 유효한 반환 유형이 아니었습니다. PHP의 동적 유형 특성을 감안할 때 많은 개발자에게 유용한 기능입니다.


class Foo { public function test(): static { return new static(); } } 


New mixed type 


어떤 사람들은 그것을 필요한 악이라고 부를 수 있습니다. 혼합 유형은 많은 사람들이 혼합 된 감정을 갖도록 만듭니다. 하지만 이를 위한 매우 좋은 주장이 있습니다 : 누락 된 유형은 PHP에서 많은 것을 의미 할 수 있습니다.


  • 함수는 아무것도 반환하지 않거나 null을 반환합니다.
  • 우리는 여러 유형 중 하나를 기대하고 있습니다
  • PHP에서 유형 힌트를 받을 수 없는 유형이 필요합니다.


위의 이유 때문에 혼합형을 추가하는 것이 좋습니다. 혼합 자체는 다음 유형 중 하나를 의미합니다.


  • array
  • bool
  • callable
  • int
  • float
  • null
  • object
  • resource
  • string

mixed은 반환 유형뿐만 아니라 매개 변수 또는 속성 유형으로도 사용할 수 있습니다.


또한 mixed는 이미 null을 포함하고 있으므로 nullable로 만들 수 없습니다. 다음은 오류를 트리거합니다.


// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type. function bar(): ?mixed {} 


Throw expression 


이 RFC 변경 사항은 명령문에서 표현식으로 던져 지므로 여러 새로운 위치에서 예외를 발생 시킬 수 있습니다.


$triggerError = fn () => throw new MyError(); $foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset'); 


Inheritance with private methods 


이전에 PHP는 public, protected 및 private 메서드에 동일한 상속 검사를 적용했습니다. 즉, private 메서드는 protected 및 public 메서드와 동일한 메서드 서명 규칙을 따라야 합니다.

이는 자식 클래스가 private 메서드에 액세스 할 수 없기 때문에 의미가 없습니다.


이 RFC는 해당 동작을 변경하여 이러한 상속 검사가 더 이상 개인 메서드에서 수행되지 않습니다. 또한 final private function를 사용하는 것도 의미가 없으므로 이제 경고가 발생합니다.


Warning: Private methods cannot be final as they are never overridden by other classes 


Weak maps 


PHP 7.4에 추가 된 weakrefs RFC를 기반으로 구축 된 WeakMap 구현은 PHP 8에 추가되었습니다. WeakMap은 객체에 대한 참조를 보유하므로 이러한 객체가 가비지 수집 되는 것을 방지하지 않습니다.


ORM의 예를 들어, 그들은 종종 엔티티 간의 관계 성능을 향상 시키기 위해 엔티티 클래스에 대한 참조를 보유하는 캐시를 구현합니다. 이러한 엔티티 객체는 캐시가 참조하는 유일한 항목이더라도 이 캐시에 참조가 있는 한 가비지 수집 할 수 없습니다.


이 캐싱 계층이 weak references와 maps을 대신 사용하는 경우 PHP는 더 이상 다른 개체를 참조하지 않을 때 이러한 개체를 가비지 수집합니다. 특히 요청 내에서 수천 개는 아니더라도 수백 개의 엔티티를 관리 할 수 있는 ORM의 경우; 약한 지도는 이러한 개체를 처리하는 더 좋고 더 자원 친화적인 방법을 제공 할 수 있습니다.


RFC의 예인 weak maps는 다음과 같습니다.


class Foo { private WeakMap $cache; public function getSomethingWithCaching(object $obj): object { return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj); } } 


Allowing ::class on objects 


작지만 유용한 새로운 기능 : 객체에 대해 get_class()를 사용하는 대신 :: class를 객체에 사용할 수 있습니다. get_class()와 같은 방식으로 작동합니다.


$foo = new Foo(); var_dump($foo::class); 


Non-capturing catches 


PHP 8 이전에 예외를 포착하고 싶을 때마다 해당 변수를 사용했는지 여부에 관계없이 변수에 저장해야 했습니다. 캡처 하지 않는 캐치를 사용하면 변수를 생략 할 수 있으므로 다음 대신 다음을 수행하십시오.


try { // Something goes wrong } catch (MySpecialException $exception) { Log::error("Something went wrong"); } 


이제 다음을 수행 할 수 있습니다.


try { // Something goes wrong } catch (MySpecialException) { Log::error("Something went wrong"); } 


항상 유형을 지정해야 하며 빈 캐치를 가질 수 없습니다. 모든 예외와 오류를 포착하려면 Throwable을 포착 유형으로 사용할 수 있습니다.


Trailing comma in parameter lists 


함수를 호출 할 때 이미 가능했지만 후행 쉼표 지원은 여전히 ​​매개 변수 목록에 부족했습니다. 이제 PHP 8에서 허용되므로 다음을 수행 할 수 있습니다.


public function( string $parameterA, int $parameterB, Foo $objectfoo, ) { // … } 


참고로, 클로저 사용 목록에서 후행 쉼표도 지원되며 이는 감독이었으며 이제 별도의 RFC를 통해 추가되었습니다.


Create DateTime objects from interface 


DateTime :: createFromImmutable ($ immutableDateTime)을 사용하여 DateTimeImmutable 개체에서 DateTime 개체를 이미 만들 수 있지만 그 반대는 까다로웠습니다. DateTime :: createFromInterface() 및 DatetimeImmutable :: createFromInterface()를 추가하면 이제 DateTime 및 DateTimeImmutable 개체를 서로 변환하는 일반화 된 방법이 있습니다.


DateTime::createFromInterface(DateTimeInterface $other); DateTimeImmutable::createFromInterface(DateTimeInterface $other); 



New Stringable interface 


Stringable 인터페이스는 __toString()을 구현하는 힌트를 입력하는 데 사용할 수 있습니다. 클래스가 __toString()을 구현할 때마다 자동으로 인터페이스를 백그라운드에서 구현하므로 수동으로 구현할 필요가 없습니다.


class Foo { public function __toString(): string { return 'foo'; } } function bar(string|Stringable $stringable) { /* … */ } bar(new Foo()); bar('abc'); 


New str_contains() function 


어떤 사람들은 기한이 늦었다고 말할 수도 있지만, 마침내 우리는 문자열에 다른 문자열이 포함되어 있는지 알기 위해 더 이상 strpos()에 의존 할 필요가 없습니다.


이렇게 하는 대신 :


if (strpos('string with lots of words', 'words') !== false) { /* … */ } 


이제 할 수 있습니다


if (str_contains('string with lots of words', 'words')) { /* … */ } 


New str_starts_with() and str_ends_with() functions 


기한이 지난 다른 두 가지 함수가 이제 코어에 추가되었습니다.


str_starts_with('haystack', 'hay'); // true str_ends_with('haystack', 'stack'); // true 


New fdiv() function 


새로운 fdiv() 함수는 fmod() 및 intdiv() 함수와 비슷한 작업을 수행하여 0으로 나눌 수 있습니다. 오류 대신 경우에 따라 INF, -INF 또는 NAN이 표시됩니다.


New get_debug_type() function 


get_debug_type()은 변수 유형을 반환합니다. gettype()이 할 수 있는 것처럼 들리나요? get_debug_type()은 배열, 문자열, 익명 클래스 및 객체에 대해 더 유용한 출력을 반환합니다.


예를 들어, \ Foo \ Bar 클래스에서 gettype()을 호출하면 객체가 반환됩니다. get_debug_type()을 사용하면 클래스 이름이 반환됩니다.


get_debug_type()과 gettype() 간의 전체 차이점 목록은 RFC에서 찾을 수 있습니다.


New get_resource_id() function 


리소스는 외부 리소스를 참조하는 PHP의 특수 변수입니다. 한 가지 예는 MySQL 연결이고 다른 하나는 파일 핸들입니다.


이전에는 해당 ID를 알 수 있는 유일한 방법이 리소스를 int로 캐스팅하는 것이었지만 이러한 리소스 각각에 ID가 할당됩니다.


$resourceId = (int) $resource; 


PHP 8은 get_resource_id() 함수를 추가하여 이 작업을 보다 명확하고 형식에 안전하게 만듭니다.


$resourceId = get_resource_id($resource); 


Abstract methods in traits improvements 


특성은 특성을 사용하는 클래스에서 구현해야 하는 추상 메서드를 지정할 수 있습니다. 하지만 주의 할 점이 있습니다. PHP 8 이전에는 이러한 메서드 구현의 서명이 검증되지 않았습니다. 다음이 유효합니다.


trait Test { abstract public function test(int $input): int; } class UsesTrait { use Test; public function test($input) { return $input; } } 


PHP 8은 트레이트를 사용하고 추상 메서드를 구현할 때 적절한 메서드 서명 유효성 검사를 수행합니다. 이것은 대신 이것을 작성해야 함을 의미합니다.


class UsesTrait { use Test; public function test(int $input): int { return $input; } } 


Object implementation of token_get_all() 


token_get_all() 함수는 값 배열을 반환합니다. 이 RFC는 PhpToken :: tokenize() 메서드를 사용하여 PhpToken 클래스를 추가합니다. 이 구현은 일반 값 대신 객체와 함께 작동합니다. 메모리를 덜 소비하고 읽기 쉽습니다.


Variable syntax tweaks 


RFC에서 : "Uniform Variable Syntax RFC는 PHP의 변수 구문에서 여러 가지 불일치를 해결했습니다.이 RFC는 간과 된 소수의 경우를 해결하려고 합니다."


Type annotations for internal functions 


모든 내부 기능에 적절한 유형 주석을 추가하기 위해 많은 사람들이 참여했습니다. 이것은 오래 지속되는 문제였으며 마침내 이전 버전에서 PHP에 적용된 모든 변경 사항으로 해결할 수 있었습니다. 이것은 내부 함수와 메소드가 완전한 유형 정보를 반영한다는 것을 의미합니다.


ext-json always available 


이전에는 JSON 확장을 활성화하지 않고 PHP를 컴파일 할 수 있었지만 더 이상 불가능했습니다. JSON은 널리 사용되기 때문에 개발자는 확장이 먼저 존재하는지 확인하는 대신 항상 거기에 의존 할 수 있습니다.


Breaking changes 


앞서 언급했듯이 이것은 주요 업데이트이므로 주요 변경 사항이 있을 것입니다. 가장 좋은 방법은 UPGRADING 문서에서 주요 변경 사항의 전체 목록을 살펴 보는 것입니다.


그러나 이러한 주요 변경 사항 중 상당수는 이전 7. * 버전에서 더 이상 사용되지 않으므로 수년 동안 최신 상태를 유지하고 있다면 PHP 8로 업그레이드하는 것이 그렇게 어렵지 않을 것입니다.


Consistent type errors 


PHP의 사용자 정의 함수는 이미 TypeError를 던지지 만 내부 함수는 그렇지 않고 오히려 경고를 내고 null을 반환합니다. PHP 8부터 내부 함수의 동작이 일관되게되었습니다.


Reclassified engine warnings 


이전에는 경고 또는 알림 만 트리거 한 많은 오류가 적절한 오류로 변환되었습니다. 다음 경고가 변경되었습니다.


  • Undefined variable: Error exception instead of notice
  • Undefined array index: warning instead of notice
  • Division by zero: DivisionByZeroError exception instead of warning
  • Attempt to increment/decrement property '%s' of non-object: Error exception instead of warning
  • Attempt to modify property '%s' of non-object: Error exception instead of warning
  • Attempt to assign property '%s' of non-object: Error exception instead of warning
  • Creating default object from empty value: Error exception instead of warning
  • Trying to get property '%s' of non-object: warning instead of notice
  • Undefined property: %s::$%s: warning instead of notice
  • Cannot add element to the array as the next element is already occupied: Error exception instead of warning
  • Cannot unset offset in a non-array variable: Error exception instead of warning
  • Cannot use a scalar value as an array: Error exception instead of warning
  • Only arrays and Traversables can be unpacked: TypeError exception instead of warning
  • Invalid argument supplied for foreach(): TypeError exception instead of warning
  • Illegal offset type: TypeError exception instead of warning
  • Illegal offset type in isset or empty: TypeError exception instead of warning
  • Illegal offset type in unset: TypeError exception instead of warning
  • Array to string conversion: warning instead of notice
  • Resource ID#%d used as offset, casting to integer (%d): warning instead of notice
  • String offset cast occurred: warning instead of notice
  • Uninitialized string offset: %d: warning instead of notice
  • Cannot assign an empty string to a string offset: Error exception instead of warning
  • Supplied resource is not a valid stream resource: TypeError exception instead of warning

The @ operator no longer silences fatal errors 


이 변경으로 인해 PHP 8 이전에 다시 숨겨 졌던 오류가 나타날 수 있습니다. 프로덕션 서버에서 display_errors = Off를 설정해야 합니다!


Default error reporting level 


이제 E_NOTICE 및 E_DEPRECATED를 제외한 모든 것이 아닌 E_ALL입니다. 즉, PHP 8 이전에는 이미 존재했지만 이전에는 조용히 무시되었던 많은 오류가 나타날 수 있습니다.


Default PDO error mode 


RFC에서 : PDO의 현재 기본 오류 모드는 자동입니다. 즉, SQL 오류가 발생할 때 오류나 경고가 발생하지 않으며 개발자가 자신의 명시 적 오류 처리를 구현하지 않는 한 예외가 발생하지 않습니다.


이 RFC는 PHP 8에서 기본 오류를 PDO :: ERRMODE_EXCEPTION으로 변경합니다.


Concatenation precedence 


PHP 7.4에서 이미 폐기되었지만 이제 이 변경 사항이 적용됩니다. 다음과 같이 작성하려면 :


echo "sum: " . $a + $b; 


PHP는 이전에 다음과 같이 해석했습니다.


echo ("sum: " . $a) + $b; 


PHP 8은 다음과 같이 해석되도록 만들 것입니다.


echo "sum: " . ($a + $b); 


산술 및 비트 연산자에 대한 엄격한 유형 검사 


PHP 8 이전에는 배열, 리소스 또는 객체에 산술 또는 비트 연산자를 적용 할 수 있었습니다. 이것은 더 이상 가능하지 않으며 TypeError가 발생합니다.


[] % [42]; $object + 4; 


Namespaced names being a single token 


PHP는 네임 스페이스의 각 부분 (백 슬래시 \로 구분)을 일련의 토큰으로 해석하는 데 사용되었습니다. 이 RFC는 해당 동작을 변경하여 이제 예약 된 이름을 네임 스페이스에서 사용할 수 있습니다.


Saner numeric strings 


PHP의 유형 시스템은 문자열에서 숫자를 만날 때 많은 현명한 작업을 시도합니다. 이 RFC는 해당 동작을 보다 일관되고 명확하게 만듭니다.


Saner string to number comparisons 


이 RFC는 0 == "foo"가 true 인 PHP에서 매우 이상한 경우를 수정합니다. 이와 같은 다른 엣지 케이스가 있으며 이 RFC는 이를 수정합니다.


Reflection changes 


몇 가지 리플렉션 방법이 더 이상 사용되지 않습니다.


  • ReflectionFunction::isDisabled()
  • ReflectionParameter::getClass()
  • ReflectionParameter::isCallable()

이제 ReflectionType을 사용하여 매개 변수 유형에 대한 정보를 가져와야 합니다.


$reflectionParameter->getType()->allowsNull(); 


유형이 단일 유형 인 경우 ReflectionParameter :: getType ()은 ReflectionNamedType의 인스턴스를 반환합니다.이 인스턴스는 이름과 내장 여부를 가져올 수 있습니다.


$reflectionParameter->getType()->getName(); $reflectionParameter->getType()->isBuiltin(); 


그러나 유형이 공용체 유형이면 ReflectionUnionType의 인스턴스를 얻게되며 다음과 같이 ReflectionNamedType의 배열을 제공 할 수 있습니다.


$reflectionParameter->getType()->getTypes(); 


유형이 공용 체인지 아닌지 확인하는 것은 instanceof check로 수행 할 수 있습니다.


if ($reflectionParameter->getType() instanceof ReflectionNamedType) { // It's a single type } if ($reflectionParameter->getType() instanceof ReflectionUnionType) { // It's a union type } 


다음으로 리플렉션 클래스의 세 가지 메서드 서명이 변경되었습니다.


ReflectionClass::newInstance($args); ReflectionFunction::invoke($args); ReflectionMethod::invoke($object, $args); 


이제 :


ReflectionClass::newInstance(...$args); ReflectionFunction::invoke(...$args); ReflectionMethod::invoke($object, ...$args); 


업그레이드 가이드는 이러한 클래스를 확장하고 PHP 7과 PHP 8을 모두 지원하려는 경우 다음 서명이 허용되도록 지정합니다.


ReflectionClass::newInstance($arg = null, ...$args); ReflectionFunction::invoke($arg = null, ...$args); ReflectionMethod::invoke($object, $arg = null, ...$args); 


Stable sorting 


PHP 8 이전에는 정렬 알고리즘이 불안정했습니다. 이는 동일한 요소의 순서가 보장되지 않았음을 의미합니다. PHP 8은 모든 정렬 기능의 동작을 안정적인 정렬로 변경합니다.


Fatal error for incompatible method signatures 


RFC에서 : 호환되지 않는 메서드 서명으로 인한 상속 오류는 현재 오류의 원인과 상속 계층 구조에 따라 치명적인 오류 또는 경고를 발생시킵니다.


Other deprecations and changes 


PHP 7. * 개발 중에 몇 가지 지원 중단이 추가되었으며 현재 PHP 8에서 마무리되었습니다.


https://stitcher.io/blog/new-in-php-8