PHP 8의 새로운 기능: 알아야 할 모든 것!

게시 됨: 2021-01-06

2020년 11월 26일 에 PHP8에 대해 연락을 드릴 예정 이며, 확실히 이 감사한 릴리스의 향후 기능에 대해 많은 내용이 작성되었습니다.

PHP 8

주요 버전이므로 주요 변경 사항과 새로운 기능이 있을 뿐만 아니라 모든 변경 사항을 인식하는 것이 중요합니다. PHP8이 앱에 어떤 영향을 미칠지, 사고 없이 편리하게 업그레이드할 수 있도록 하려면 어떤 조치를 취해야 하는지 생각하는 것이 편리할 것입니다.

우리는 다음 PHP 릴리스에서 얻을 수 있는 것과 비판할 가치가 있는 것을 파악하기 위해 가장 중요한 몇 가지 변경을 거쳤습니다.

개요부터 시작하겠습니다!

PHP 8 개요

위에서 언급했듯이 PHP 8은 언어에 새로운 기능, 개선 사항, 기능 및 사용 중단을 도입했습니다. 이 중에서 가장 많이 논의되는 기능은 JIT 컴파일러입니다. 그러나 JIT와 같은 성능 향상 기능은 각광을 받을 만하지만 구문 개선은 "최소한 단기적으로는" PHP 실무자에게 더 큰 타격을 줄 것으로 예상됩니다.

변화의 역사

몇 가지 PHP 변경 사항이 제안되고, 논의되고, 구현되고, 단기간에 추가로 승인됩니다. 그들은 인기 있고 논쟁의 여지가 없으며 구현하는 자연스러운 방법을 가지고 있습니다.

그리고 그 후에 우리가 마침내 그것을 받아들이기 전에 여러 번 시도하고, 실패하고, 반환하는 것들이 옵니다. 몇 번 구현은 정리하는 데 오랜 시간이 걸리고 때로는 아이디어 자체가 반쯤 구겨지고 때로는 커뮤니티 자체가 아직 아이디어를 예열하지 않은 경우도 있습니다. "아직 시간이 아닙니다."

크레딧은 정확히 유형 범주에 속합니다. PHP 7.1용으로 2016년 처음 제안되었습니다 . 그러나 그들은 완강한 저항에 부딪혀 큰 차이로 승인 표를 잃었습니다. 이제 4년을 앞당기고 약간 축소된 범위의 제안이 단 한 명의 반대자에게만 떠돌았지만 꽤 유사했습니다. 그것은 분명히 누구의 시간이 확실히 도래한 아이디어입니다!

이전 코드의 문제점은 무엇입니까?

PHP 8은 거대한 새 릴리스이므로 이전 코드가 더 이상 호환되지 않을 것으로 예상해야 합니다. 그러나 합병증을 유발할 수 있는 변경 사항의 대부분은 이미 버전 7.2 , 7.3 7.4 에서 전달되었습니다 . 이제 마지막 변경 사항에 대해 이야기해 보겠습니다. 그들은:

마법의 인용문 유산

  • 실제 유형
  • FILTER_SANITIZE_MAGIC_QUOTES 필터
  • 비정적 클로저에서 $this 바인딩 해제
  • 객체가 있는 array_key_exists()
  • 세 번째 인수로 인코딩을 사용하는 mb_strrpos()
  • 반사 export() 메서드
  • convert_cyr_string() 함수
  • implode() 매개변수 순서 혼합
  • restore_include_path() 함수
  • hebrevc() 함수
  • money_format() 함수
  • allow_url_include ini 지시문
  • ezmlm_hash() 함수

PHP 8의 새로운 기능

str_contains

한 문자열에 다른 문자열이 포함되어 있으면 여러 가지 방법으로 찾을 수 있습니다.

일반적으로 strpos()를 사용합니다. 아시다시피 strpos()는 찾고자 하는 바늘 옆에 건초 더미를 가져옵니다. 바늘이 보이는 첫 번째 위치를 나타내는 정수를 반환합니다.

이제 다른 문자열의 위치를 ​​반환하므로 strpos()가 문자열을 발견했는지 여부를 확인할 수 없습니다. "0"을 반환하면(위치가 0으로 인덱싱되고 1이 아닌 0으로 시작함) 조건부는 이를 false 값으로 처리하고 찾을 수 없음을 나타냅니다.

그게 무슨 뜻이야?

조건부 –“strpos($haystack, $needle) !== false”를 작성해야 합니다. False는 문자열의 위치를 ​​찾을 수 없음을 나타냅니다. 이것은 문자열에서 문자열을 검색하는 불투명하고 난해한 방법입니다! 글쎄, 그렇게 혼란스럽지 않습니다.

이를 피하기 위해 PHP 8은 str_contains()를 제공합니다. str_contains()의 역할은 바늘이 건초 더미에 있는지 여부를 보여주는 간단한 부울 값을 반환하는 것입니다. 코드를 유지 관리하는 사람으로 이해하는 것 외에도 작성하기가 훨씬 쉽죠?

 if (str_contains( 'Foo Bar Baz' , 'Foo' )) { // FOUND }

PHP 8: 엔진 기능 및 변경 사항

몇 가지 새로운 엔진 기능과 PHP 8에서 변경된 사항이 있습니다. 헤드라이닝 기능은 의심할 여지 없이 새로운 JIT 컴파일러입니다.

JIT 컴파일러

  • LSP 시행
  • 호환되지 않는 메서드 서명에 대한 치명적인 오류
  • 리소스 "클래스"
  • XML-RPC는 이제 PECL에 있습니다.
  • 어설션 동작
  • 반사 변경

이 블로그의 핵심 목적을 위해 JIT 컴파일러, 리소스 "클래스" 및 마지막으로 리플렉션 API 변경 사항에 중점을 둘 것입니다.

Just-In-Time 컴파일러( RFC )

PHP7이 출시되기 전의 속도 향상으로 인해 Just-In-Time(또는 JIT) 컴파일러가 탄생했습니다. JIT를 사용하지 않고 가져올 수 있는 속도 향상이 거의 없기 때문에 PHP8에 도입되었습니다. 아이디어는 PHP 성능을 향상시키는 것입니다.

PHP 코드는 실행될 때 바이트 코드로 변환되며, 이러한 바이트 코드는 프로그램의 단계를 실행하는 데 추가로 활용됩니다.

PHP는 실행한 코드를 분석합니다. 이것이 JIT가 의미하는 것입니다. 또한 코드를 실행할 때 성능 향상 이외의 실시간 결정을 내릴 수 있습니다. 웹 기반 시나리오에서 사용되는 동안뿐만 아니라 CPU 집약적인 애플리케이션에서 매우 유용할 것입니다.

이는 서버 측 PHP 애플리케이션이 PHP 내장 JIT 시스템에서 확실히 더 널리 퍼질 수 있음을 반영합니다.

JIT를 사용하려면 먼저 JIT를 활성화해야 합니다. 테스트 시스템(Ubuntu 20.04)에는 이미 핵심 PHP8 패키지와 함께 설치한 PHP opcache 모듈이 설치되어 있습니다. /etc/php/8.0/cli/conf.d/10-opcache.ini에 있는 파일에서 구성했습니다.

이제 JIT를 활성화할 준비가 모두 되었습니까?  

  • opcache 활성화

opcache.jit_buffer_size 설정에 메모리 스토리지를 할당할 수 있습니다. 귀하의 파일은 내 시스템에 다음과 같이 표시됩니다.

  1. zend_extension=opcache.so
  2. opcache.enable_cli=1
  3. ; PHP opcache 모듈 구성
  4. opcache.jit_buffer_size=256M

또한 opcache_get_status() 함수를 사용하여 활성 여부를 확인합니다. 이 배열의 'jit' 부분 위로 시선을 돌리고 JIT의 현재 상태에 대한 정보를 얻으십시오.


var_dump(opcache_get_status()['jit']);

JIT가 완벽하게 활성화된 경우 아래 그림과 같이 인쇄되어야 합니다.

  1. 배열(7) {
  2. ["활성화"]=>
  3. 부울(참)
  4. ["켜기"]=>
  5. 부울(참)
  6. ["종류"]=>
  7. 정수(5)
  8. [“opt_level”]=>
  9. 정수(4)
  10. ["opt_flags"]=>
  11. 정수(6)
  12. [“버퍼 크기”]=>
  13. 정수(268435440)
  14. [“buffer_free”]=>
  15. 정수(268432880)
  16. }

그래서 더 빨랐나? 한마디로 우리는 따뜻한 "예"라고 외칠 것입니다.

우리는 몇몇 사람들이 만델브로트 세트의 도움으로 벤치마크를 하는 것을 보았고, 그래서 우리는 PHP에서 몇 가지 다른 종류의 프랙탈을 그리는 우리가 얼마 전에 만든 라이브러리를 사용하기로 결정했습니다. 우리가 한 것은 세 개의 프랙탈을 생성하고 microtome() 함수를 사용하는 데 걸리는 시간을 추적하는 것뿐이었습니다. 아래에 PHP 7.4.8에 대한 결과를 표시했습니다.

  • 버닝쉽 – 84.20269203186
  • 맨들 브로트 – 21.552599906921
  • 트라이콘 - 32.685042858124

PHP8에서 동일한 코드를 실행했을 때 속도가 상당히 빨랐습니다. 숫자가 스스로 말해줄 것입니다. .

  • 버닝쉽 – 15.272277116776
  • 맨들브로트 -3.7528541088104
  • 트라이콘 -4.4957919120789

이 엄청난 속도 증가는 꽤 흥미롭습니다. 여기에서 사용한 코드는 거대한 크기의 프랙탈을 생성하지만 코드를 생성할 때 대부분의 시간을 프랙탈 생성을 기다리는 데 보냈다는 것을 기억합니다.

이 추가는 우리가 PHP를 어떤 경우에(프랙탈 생성 이외의) 한계까지 밀어붙였기 때문에 흥미롭습니다. 이것이 PHP의 미래에 큰 도움이 된다는 것을 알 수 있으며 일반 웹사이트 언어 이외의 상황에서 언어를 선택할 수 있도록 할 것입니다.

WordPress 또는 Drupal과 같은 앱의 속도 증가는 살펴보지 않았지만 읽은 내용에 따르면 이러한 종류의 응용 프로그램에는 확실히 차이가 거의 없습니다. 앞으로 우리는 이러한 플랫폼에서 벤치마크를 실행하여 JIT가 그곳에서 어떤 종류의 차이를 표시하는지 알아낼 것입니다.

연합 유형( RFC )

PHP7부터 어떤 종류의 반환 값과 인수의 유형을 규정하고 가능하게 되었습니다. 이렇게 하면 전달하는 인수 유형이 예상 유형과 동일하지 않은 경우 PHP가 오류를 던질 수 있습니다. 함수가 PHP와 같은 느슨한 유형의 언어에서 완벽한 유형의 값을 수신하고 생성하도록 하는 것이 중요합니다.

PHP8에서는 이제 파이프 문자로 분할된 인수 및 반환 값에 대한 다양한 정렬을 규정할 수 있습니다.

부동 소수점 또는 정수 값을 받을 수 있는 함수를 아래에 표시했습니다.

 function addNumbers(int|float $number1, int|float $number2) : int|float { return $number1 + $number2; }

이전에는 전달된 인수가 올바르지 않은 경우 PHP가 자동으로 유형을 보여줄 수 있기 때문에 이와 동일한 함수를 유형 힌트 없이 생성해야 했습니다. 이는 인수 유형을 정수로 설정하는 경우 PHP가 모든 부동 소수점 값을 정수로 표시한다는 것을 의미했습니다. 단위 테스트를 하지 않는 경우에 잡아야 하는 몇 가지 까다로운 버그가 발생할 수 있습니다.

우리는 위의 기능을 사용하기 위해 다른 것과 같이 호출합니다.

 echo addNumbers(1, 1); // prints 2 echo addNumbers(1.1, 1.1); // prints 2.2

동일한 함수에 문자열을 전달하려는 경우:

 echo addNumbers('one', 'two');

함수에 float 또는 "int"를 전달해야 한다고 주장하는 PHP Fatal 오류가 발생합니다.

함수가 아무 것도 반환하지 않는다고 규정하기 때문에 void 유형을 공용체 유형으로 사용할 수 없습니다. 간단히 말해서, 함수가 void 또는 정수를 반환할 것이라고 외칠 수 없습니다. PHP 치명적인 오류가 발생합니다.

일반적인 변경 사항이지만 이전에는 주석에서 다양한 유형의 값을 규정할 수 있었기 때문에 이 기능이 약간 사용되었음을 알 수 있습니다. 그 결과 문서 블록 주석이 코드보다 더 상세해졌습니다.

Nullsafe 연산자(RFC)

null 병합 연산자 외에도 null 반환 값을 감지하는 기능은 메서드에서 직접 가능합니다. 모르는 경우 null 병합 연산자를 사용하여 값을 얻을 수 있으며 첫 번째 값이 null인 경우 다른 값을 반환하는 것 외에 값이 있는지 테스트할 필요가 없습니다.

따라서 "$_GET superglobal"에서 값을 가져오기 위해 이 작업을 수행할 수 있습니다. 해당 값이 없으면 "0"입니다.


1. $page = $_GET['page'] ?? 0;

2. 에코 $page;

null 안전 연산자의 작업은 동일하지만 해당 값을 사용하기 전에 편리한 바로 가기를 만들고 null 반환을 테스트할 수 있습니다.

우리는 이것이 "메소드로부터의 반환" 또는 "객체 속성"을 사용하기 전에 내용이 포함되어 있는지 확인하기 위해 많은 검사 코드를 작성하는 경향이 있는 Drupal에서 궁극적으로 유용할 것이라는 사실을 알게 되었습니다. 이것은 포함된 내용으로 인해 Drupal의 개체의 컨텍스트 상태 때문에 필수입니다. 이 변경은 확실히 일부 검사를 단순화할 것입니다.

명명된 인수( RFC )

명명된 인수를 사용하면 인수 및 호출 함수의 다른 순서를 규정할 수 있습니다. 두 개의 매개변수가 있는 다음 일반 함수를 사용합니다. 주어진 길이만큼 배열을 채웁니다.

 function fillArray(array $arrayToFill, int $number) : array { for ($i = 0 $i < $number; ++$i) { $arrayToFill[$i] =1; } return $arrayToFill; }

우리는 그들이 정의한 배열에서 인수를 전달할 수 있으며 일반적인 방식으로 이 기술을 호출할 수 있습니다.

 $newArray = fillArray([], 2);

PHP8부터는 매개변수를 함수에 전달할 때 매개변수의 이름을 지정할 수 있습니다. 또한 원하는 순서대로 매개변수를 보낼 수 있습니다.

 $newArray = fillArray(number: 2, arrayToFill: []);

일반적인 예지만 코드를 더 읽기 쉽게 만들 수도 있습니다.

이 기술은 사용자 정의 기능뿐만 아니라 PHP의 모든 기능에서 작동합니다. PHP 언어에서 배열 및 문자열 함수는 매개변수의 순서가 동일하지 않습니다. 정말 환영할만한 추가 사항입니다.

속성 V2( RFC1 RFC2 RFC3 )

속성은 메타데이터를 PHP 클래스, 함수, 클래스 속성, 함수 매개변수 및 상수에 연결하는 메커니즘을 제공합니다. 코드를 통해 직접 액세스할 수 없으며 PHP에 내장된 리플렉션 클래스를 사용하여 가져와야 합니다.

ReflectionClass 클래스는 PHP5부터 PHP에 있습니다. 그러나 getAttribute() 메서드는 PHP8의 새로운 기능입니다. 이 메서드는 속성에 대한 정보를 포함할 ReflectionAttribute 개체의 범위를 반환합니다.

이 추가에는 몇 가지 변경 사항이 있었습니다(위의 여러 RFC에서 알 수 있듯이). 클래스를 인스턴스화하는 경우 ReflectionClass를 사용하고 클래스 수준에 포함된 속성 정보를 인쇄할 수 있습니다. PHP8에는 많은 속성이 있으므로 RFC를 읽고 RFC의 실제 내용과 코드에 통합하는 방법에 익숙해지는 것이 좋습니다.

일치 표현식( RFC )

PHP 8에서는 새로운 일치 표현식을 약식 switch 문과 비교할 수 있습니다.

전달된 값을 기반으로 값을 반환하는 함수 선언처럼 보입니다.

여러 if 문을 모두 포함하지 않고 동일한 표현식의 조건을 확인하려는 경우 PHP의 switch 문은 놀랍습니다.

여기에서는 동일한 표현식에 대한 기본적인 if-else 비교를 제공합니다.

 <?php if ($i == 'apple') { echo 'i is apple'; } elseif ($i == 'cake') { echo 'i is cake'; } else { echo 'i is pizza'; }

그리고 이것은 이전 예제의 동등한 switch 문이 다음과 같이 표시되는 방식입니다.

 <?php switch ($i) { case 'apple': echo 'i is apple'; break; case 'cake': echo 'i is cake'; break; default: echo 'i is pizza'; }

리소스 "클래스"

리소스 "클래스"는 PHP 8의 주요 변경 사항 목록에 있으며 주어진 리소스 유형에 대해 인스턴스화할 수 없는 대체물 역할을 합니다. 사용 가능한 대체품은 다음과 같습니다.

  • CurlHandle — 이제 curl_init()가 컬 리소스와 관련된 CurlHandle을 반환합니다.
  • Socket / AddressInfo — 소켓 확장에 의해 제공됩니다. socket_*() 함수의 수량은 Socket을 반환하는 반면 socket_address_info_lookup() 함수는 AddressInfo 인스턴스를 반환합니다.
  • GdImage — 수많은 imagecreatefrom*() 함수에 의해 복원된 GD 리소스를 나타냅니다.

또한 curl_close()와 같은 함수에 의해 리소스가 파괴되지 않는다는 점에 유의하는 것이 중요합니다. 오히려 인스턴스가 이제 클래스 인스턴스이므로 역참조를 위해 인스턴스를 unset()해야 합니다.
함수와 메서드에서 클래스를 typehint로 지정할 수 있는 기능을 얻습니다.
이전에는 유형이 지정되지 않은 값을 반환하거나 리소스 인수를 남겨두고 주석을 통해 문서화해야 했지만 이제는 명시적 유형을 사용할 수 있으며 이는 코드를 더 읽기 쉽게 만들 뿐만 아니라 더 유형 안전합니다.
여기서 절충안은 무엇입니까?
리소스를 제거하는 데 사용된 이전 함수 대신 unset()을 사용하여 리소스를 제거하려면 이제 코드를 업데이트해야 합니다. 이것은 일반적으로 검색 및 바꾸기를 통해 수행할 수 있습니다.

리플렉션 API 변경 사항

또 다른 작은 것이지만 PHP 8의 중요한 변경 사항은 Reflection API와 관련이 있습니다. 속성 시스템을 사용하는 동안 모든 리플렉션 클래스에서 리플렉션 API를 통해 해당 속성을 편리하게 검색할 수 있습니다.
혼합 및 공용체 유형이 추가되어 ReflectionParameter 기술 getClass(), isCallable() 및 isArray()가 이제 더 이상 사용되지 않습니다.
시나리오는 getType()을 사용하는 것이 훨씬 더 좋으며 특정 매개변수가 충족하는 유형의 전체 목록을 얻을 수 있기 때문입니다.

PHP 8 구문 개선

우리가 눈치채고 있듯이 JIT는 헤드라인을 훔치고 있습니다. PHP 8 구문 개선은 PHP 개발자에게 삶의 질을 크게 향상시키는 이점을 제공합니다.
승격된 생성자 인수 사이의 공통 상용구를 제거하거나 향상된 예외 및 오류 처리를 제거하는 것과 상관없이 개발자가 기뻐할 일이 많습니다.

  • "혼합" 유사 유형
  • 조합 유형
  • 클래스 생성자 속성 승격
  • 표현식에서 예외 던지기
  • 속성
  • ::클래스 유비쿼터스
  • 유형별로만 잡기
  • 일치 표현식

이 블로그의 목적을 유지하기 위해 우리는 공용체 유형, 속성 및 일치 표현식에 중점을 두고 있습니다.

조합 유형

Union 유형은 값이 둘 이상의 지정된 정렬 중 하나임을 나타냅니다. 허용되는 모든 단일 유형 사이에 수직 막대를 배치하여 수행됩니다. 값을 반환하거나 매개변수를 지정하기 위해 PHP 주석에 깊이 있는 여러 개발자의 경우 이미 이 작업을 수행하고 있을 가능성이 큽니다.
Union 유형은 많은 다른 유형을 수락하거나 많은 다른 유형을 반환하는 사람들에게 훨씬 복잡하고 이해하기 어려울 수 있습니다.
그래도 이것은 여러 경우에 매우 유용할 것입니다. 예를 들어, 새로운 Stringable 인터페이스("string|Stringable") 또는 문자열을 구현하는 객체를 수락할 수 있는 경우 또는 Traversable 인터페이스("array|Traversable") 또는 배열을 구현하는 객체를 수락할 수 있는 경우 .

일치 표현식

일치 표현식은 주어진 스위치 케이스 내에서 중단 실패가 의도적인 것인지 여부를 파악하는 것과 관련된 추측을 차단합니다. 또한 일치를 기반으로 값을 할당하는 일반적인 패턴을 단순화합니다.
사용할 때 match()에 전달하는 값은 왼쪽에 있는 표현식과 직접 비교됩니다. 그것이 표현식이든 값이든, match()에 전달하는 값은 선택하기 위해 일치해야 합니다.
일치하면 오른쪽에 있는 식이 추정되고 반환 값이 반환됩니다. 반면 식은 Lambda 또는 호출 가능 함수일 수 있고 여러 줄 클로저가 허용되지 않습니다.

속성

PHP 8은 언어 수준에서도 속성을 통합합니다. 속성은 docblock 주석을 통해 15년 이상 존재하지만 언어에 속성을 구축하면 성능이 향상되고 확실히 더 강력하고 일관성이 높아집니다. 도구 및 빠른 응용 프로그램의 개발에서 속성이 많이 사용되는 것을 보게 될 것입니다.

결론

확실히 PHP8에는 몇 가지 변경 사항이 있습니다. 그래도 제거되는 대부분의 사용되지 않는 코드는 최근에 사용된 적이 없는 이전 기능을 위한 것 같습니다.
우리는 JIT 엔진이 우리가 사용하는 코드베이스와 더 넓은 PHP 커뮤니티에 어떤 영향을 미칠지 주목하고 있습니다. 즉, PHP8과의 비호환성에 대해 코드베이스를 스캔하고 PHP가 업그레이드에 "예"라고 말하기 전에 응용 프로그램이 완벽하게 작동합니다.