PHP Annotated — May 2021
Roman Pronskiy가 쓰고 JetBrains에서 제공하는 PHP Annotated 2021년 5월호의 번역/해석본입니다.
이 중에서 몇 가지 제 취향껏 골라 그 안의 내용도 좀 뒤져보고 개발새발 번역해서 소개합니다.
Composer의 통계에 따르면 PHP 8.0이 추진력을 얻고 있으며 더 많이 채택되고 있습니다.
한편, PHP internals에선 번들로 제공되는 PHP 확장의 네임 스페이스, 새로운 never 유형, 더 이상 사용되지 않을 일부 기능을 포함한 PHP 8.1에 대한 많은 변경 사항을 수용했습니다.
PHP 8.1 릴리스 관리자(release managers)가 선택됐으며 속성 접근자(property accessors), 순수 교차 유형(pure intersection types) 및 final 상수(final constants)를 포함하여 몇 가지 흥미로운 제안이 논의 중입니다.
⚡️ News
PHP Versions Stats – 2021.1
https://blog.packagist.com/php-versions-stats-2021-1-edition/
Composer가 packagist.org에 연결할 때 전송하는 데이터를 기반으로하는 전통적인 통계 기록:
- PHP 7.4: 45.92% (+3.31)
- PHP 7.3: 21.30% (-5.75)
- PHP 7.2: 12.89% (-2.39)
- PHP 8.0: 9.44% (+9.17)
- PHP 7.1: 5.21% (-2.24)
PHP is available on Google Cloud Functions
https://cloud.google.com/blog/products/application-development/php-comes-to-cloud-functions
Google Cloud의 서버리스 플랫폼은 이제 PHP를 정식으로 지원합니다. GoogleCloudPlatform/functions-framework-php를 사용하면 PHP 7.4 기반 런타임에서 function을 실행할 수 있습니다.
Composer Command Injection Vulnerability
https://blog.packagist.com/composer-command-injection-vulnerability/
이번 Composer의 취약점은 Mercurial이 설치된 시스템에만 영향을줍니다. 그러나 수정 사항이 포함된 2.0.13 및 1.10.22 버전으로 즉시 업데이트하는 것이 좋습니다. 취약점에 대한 더 자세한 기술 분석을 확인하십시오.
Follow up on git.php.net attack
https://externals.io/message/113981
공격자들은 Rasmus Lerdorf와 Nikita Popov를 대신하여 두 개의 커밋을 PHP 소스에 푸시했습니다. 문제는 신속하게 감지되고 해결되었습니다. 악성 코드는 사용자에게 전달되지 않았습니다.
git.php.net 서버는 HTTPS를 통한 커밋을 허용하고 md5 해시를 secret으로 허용하는 다이제스트 인증을 사용한 것으로 나타났습니다. 모든 contributor의 해시 데이터베이스는 master.php.net에서 공격자에 의해 획득되었으며, 아마 원래는 손상된 서버일 것입니다.
결과적으로 모든 개발이 GitHub로 완전히 옮겨져 언어 개발자의 삶이 더 편해졌습니다.
PHP 7.4.19, PHP 8.0.6
https://www.php.net/ChangeLog-7.php#7.4.19
https://www.php.net/ChangeLog-8.php#8.0.6
With a fix in PDO_pgsql.
🐘 PHP Internals
✅ [RFC] never type
PHP 8.1에는 반환 값에 never라는 새로운 type이 추가됩니다.
never type으로 선언된 함수 또는 메서드는 값을 반환하지 않을 것임을 나타내며 예외를 throw하거나 die(), exit(), trigger_error() 유형의 호출로 종료됩니다.
이는 bottom type이며 다른 모든 type의 하위 type이며 Python, Rust, Kotlin 및 TypeScript에 유사한 type이 있습니다. 이 type은 정적 분석을 향상시킵니다.
function redirect(string $uri): never { |
RFC는 이름부터 noreturn으로 제안이 됐지만, 투표로 최종 never로 결정됐습니다. RFC의 Naming 섹션 참고하세요.
자세한 내용은 PHP.Watch에서 보거나 Matt Brown과 Ondřej Mirtes가 함께 하는 PHP Internals News podcast에서 들을 수 있습니다.
✅ [RFC] Deprecate implicit non-integer-compatible float to int conversions
https://wiki.php.net/rfc/implicit-float-int-deprecate
PHP 8.1에서는 float가 int로 변환되고 소수 부분이 손실되면 E_DEPRECATED 알림이 발생합니다. 나중에 PHP 9.0에서는 TypeError가 발생합니다.
function acceptInt(int $i) { |
George Peter Banyard와 함께 하는 🔈 PHP Internals News podcast #83에서 자세히 알아보세요.
✅ [RFC] Phasing out Serializable
https://wiki.php.net/rfc/phase_out_serializable
PHP 8.1에서는 Serializable 인터페이스가 더 이상 사용되지 않습니다. 클래스가 오직 이 인터페이스만 사용하는 경우, 즉 클래스에 새로운 매직 메서드인 __serialize() 및 __unserialize()가 추가로 없는 경우 deprecation 알림이 발생합니다.
✅ [RFC] Namespaces in bundled PHP extensions
https://wiki.php.net/rfc/namespaces_in_bundled_extensions
이것은 더 깨끗한 PHP를 향한 작은 발걸음입니다! Extension의 새로운 심볼(클래스, 인터페이스 등)은 이제 네임 스페이스를 사용해야합니다.
여기 예시가 있습니다. resource type은 PHP에서 사실상 더 이상 사용되지 않으며 기존의 모든 리소스가 천천히 object로 마이그레이션되고 있습니다. PHP 8.1에서 일부 리소스는 다음 네임 스페이스 클래스로 대체됩니다.
IMAPConnection -> IMAP\Connection |
✅ [RFC] Add return type declarations for internal methods
https://wiki.php.net/rfc/internal_method_return_types
PHP 8.0에 내장된 대부분의 메소드는 매개 변수를 받고 유형 선언을 반환합니다. 그러나 문제는 public non-final 메서드의 반환 값과 같이 사용자 코드에서 재정의 될 수 있는 경우입니다.
class SomeStandardClass |
공변(covariance) 규칙에 따라, 재정의된 메소드에 다른 반환 type을 추가할 수 있지만, 메소드 시그니처가 다르면 하위 호환이 깨집니다. PHP 프로젝트 리더들은 아직 큰 하위 호환 문제를 일으키지 않도록 장기적/점진적으로 마이그레이션을 할 수 있게 지원하기로 했습니다.
PHP 8.1에서 모든 내부 메서드는 누락된 type도 가져옵니다. 사용자 코드에서 재정의 된 경우 사용 중단 알림이 표시됩니다.
class MyDateTime extends DateTime |
Release managers for PHP 8.1 have been selected
https://wiki.php.net/todo/php81#release_managers
이번 릴리스에서는 세 명의 release manager가 있습니다.
경험이 풍부한 Joe Watkins (pthreads, parallel, pcov)와 두 명의 신참 인 Patrick Allaert (blackfire.io) 및 Ben Ramsey (ramsey/uuid)의 세 명의 관리자가 있습니다. Ben과 Patrick이 함께 하는 PHP Internals News podcast #84를 확인하십시오.
New proposals for PHP 8.1:
[RFC] Partial Function Application
https://wiki.php.net/rfc/partial_function_application
Partial Function Application은 일부 인수만 함수 호출에 바인딩되고 나머지 인수는 나중에 전달될 매개 변수로 남아있는 경우입니다.
예를 들어, 여기 전체 함수가 있습니다.
function whole($one, $two) { |
이 전체 함수를 기초로 부분 함수가 있습니다.
$partial = whole(?, 2); |
이제 이 부분 함수의 시그니처는 아래와 같습니다.
function($one) { |
이게 왜 필요하죠?
첫째, 이제 모든 함수 또는 메서드에 대한 참조를 가져 와서 Callable이 예상되는 곳에 전달할 수 있습니다. 예를 들어 다음과 같이 할 수 있습니다.
array_map(Something::toString(?), [1, 2, 3]); |
둘째, 결과적으로 파이프 연산자 |>를 구현할 수 있습니다.
$result = "Hello World" |
RFC 및 구현에 대해 Larry Garfield, Joe Watkins, Levi Morrison 및 Paul Crovella에게 감사드립니다.
[RFC] Property Accessors
https://wiki.php.net/rfc/property_accessors
Nikita는 속성 접근자의 구현을 완료했으며 현재 제안은 공식적으로 논의 중입니다.
결론은 기존의 getter 및 setter는 사용하기 편리하지 않으며 매직 메서드 __get 및 __set은 구체적이지 않다는 것입니다. 새로운 접근자는 이러한 문제를 해결하기위한 것입니다.
C#에서 영감을 얻은 문법:
class Foo { |
이를 사용하여 읽기 전용 속성을 구현할 수 있습니다.
class User { |
비대칭 액세스를 지정할 수 있습니다. 즉, 읽기 및 쓰기를 위해 별도로 공개 또는 비공개로 설정할 수 있습니다.
class User { |
또는 유효성 검사 또는 기타 작업을 위한 완전히 구현된 메소드로 사용할 수 있습니다.
class Foo { |
[RFC] Pure intersection types
https://wiki.php.net/rfc/pure-intersection-types
통합 유형은 PHP 8.0에 추가되었으며 이 RFC는 교차 유형 추가를 제안합니다.
구문은 TypeA & TypeB이며, 이는 변수가 TypeA 및 TypeB의 인스턴스여야 함을 의미합니다.
class A { |
이 제안을 “순수 교차 type”이라고합니다. union type의 조합은 지원되지 않으며 향후 고려할 수 있도록 남아 있기 때문입니다. 복잡한 유형에 대한 별칭도 미래를 위해 남아 있습니다.
[RFC] Deprecate ticks
https://wiki.php.net/rfc/deprecate_ticks
PHP에는 틱 매커니즘이 있습니다 : declare(ticks=1)
. 원래 pcntl 신호를 추적하는 데 필요했습니다. 이제 pcntl_signal() 및 pcntl_async_signals()를 대신 사용할 수 있습니다. 이것이 PHP 8.1에서 틱을 폐기하고 PHP 9에서 완전히 제거하라는 제안이 있었던 이유입니다.
[RFC] Final class constants
https://wiki.php.net/rfc/final_class_const
이 RFC의 작성자는 상수에 대한 final 수정자를 제안하므로 자식 클래스에서 재정의 할 수 없습니다.
class Foo |
흥미로운 사실은 인터페이스 상수는 이미 final이라는 것입니다.
PHP 소스에 기여하고 싶은 사람들을위한 몇 가지 추가 링크
- PHP 8.1의 릴리스 관리자 중 하나인 Ben Ramsey의 지침입니다.
How to compile PHP from source on Debian/Ubuntu
- Beginner’s guide on PHP.Watch.
🛠 Tools
spatie/data-transfer-object v3
https://github.com/spatie/data-transfer-object
spatie가 PHP 8에서 type이 정의된 DTO를 쉽게 만들기 위한 패키지를 만들었습니다.
spatie/fork
https://github.com/spatie/fork
pcntl_fork를 위한 래퍼로 PHP 스크립트를 병렬로 간단하고 편리하게 실행할 수 있습니다. 이 블로그 게시물과 이 비디오에서 자세히 알아보십시오.
phpbench/phpbench 1.0.0
https://github.com/phpbench/phpbench/releases/tag/1.0.0
코드를 벤치마킹하는 데 유용한 도구입니다. 새 버전에는 PHP 8 지원을 포함하여 많은 업데이트가 있습니다.
Dan Leech와 함께 📺 Release Radar #10에서 더 알아보세요.
rybakit/phpunit-extras
https://github.com/rybakit/phpunit-extras
테스트를 더 깔끔하게 만들 PHPUnit을 위한 커스텀 annotation과 expect*()
메소드.
infection 0.23.0
https://infection.github.io/2021/05/13/whats-new-in-0.23.0/#Pest-Test-Framework-support
Mutation 테스트 지원 도구가 업데이트 됐습니다. 이제 pestphp/pest를 지원합니다.
captainhookphp/captainhook
https://github.com/captainhookphp/captainhook
PHP 프로젝트를 위한 Git hook 관리. 예를 들어, 스타일 검사를 쉽게 설정하거나 저장소로 푸시하기 전에 테스트를 실행할 수 있습니다.
0xABADCAFE/php-demo-engine
https://github.com/0xABADCAFE/php-demo-engine
재미로 만든 PHP의 데모씬 엔진. 콘솔에 ASCII 기호가있는 그래픽을 표시합니다.
Symfony
-
- Silex 마이크로 프레임워크는 더는 사용되지 않으며 꽤 오랫동안 지원되지 않았지만, 이 관리되는 포크로부터 구출될 수 있습니다.
Laravel
-
- 이 패키지를 사용하면 Swoole 또는 RoadRunner에서 Laravel을 실행할 수 있습니다. 부트 스트랩을 한 번 실행 한 다음 각 요청을 동일한 애플리케이션 인스턴스에서 처리합니다. Mohamed Said의 게시물과 Marcel Pociot의 게시글에서 애플리케이션 개발자를 위한 변경 사항에 대해 자세히 알아보십시오.
-
- Laravel으로 SaaS를 생성하기 위한 스켈레톤. 사용자 프로필, 구독, API, 관리자 및 블로그가 즉시 제공됩니다.
laravel-arcanist/arcanist
- 여러 단계의 마법사를 구축하기 위한 패키지. Kai Sassnowski의 📺 자세한 설명을 확인해보세요.
-
- 무거운 JSON을 illuminate/support의 lazy collection에 담기 위한 패키지
-
- Laravel에 구축 된 mailinator.com과 같은 일회용 이메일 주소 서비스.
-
- Spatie 사람들의 유료 강의. 일부는 무료로 제공됩니다.
Yii
-
- Yii 3 및 Yii 2 릴리스 세트에 대한 뉴스, 코드와 직접 관련은 없지만 흥미로운 프로젝트도 소개합니다.
New packages for Yii 3: yiisoft/profiler, yiisoft/error-handler, yiisoft/translator, yiisoft/yii-event, yiisoft/assets.
PhpStorm
- Using PhpStorm’s Live Templates for Doctrine fields.
- A quick way to browse Symfony logs in PhpStorm with Ideolog.
- 정규식으로 시간을 꽤 투자해서 설정해야 하기 때문에 불평이 굉장히 많은 플러그인인데, 누군가 미리 설정한 preset을 활용하면 도움이 될 수도 있겠습니다. dszczer/ideolog-symfony-format에서 영감을 받았다고 하네요.
- Fully integrate DDEV and PhpStorm
- Coverage와 단위 테스트를 실행하는 방법을 포함하는 DDEV와 PhpStorm 연동
💡 기타 읽을 만한 글
Upgrading a Project to PHP 8.0
https://medium.com/oro-development/upgrade-to-php-8-64f770ae4479
PHP 7.4에서 8.0으로 업그레이드 할 때의 업데이트 계획 및 코드베이스를 주요 잠재적 어려움에 대한 설명.
작성자가 업그레이드 했던 코드는 Symfony 4.4 LTS, 300만 이상의 LoC, 60만 PHP class, test 코드 포함, vendor 제외.
결론
- 오픈 소스 커뮤니티는 PHP 릴리스를 적극적으로 모니터링하고 새로운 버전의 PHP에 대한 지원을 라이브러리에 추가합니다.
- composer.json에서 실제로 지원되는 PHP 버전 만 나열하면 composer가 기본 제공하는 종속성 분석기(
composer why-not php 8
) 덕분에 프로젝트에서 이런 라이브러리를 사용하는 개발자에게 큰 도움이됩니다. - PHPStorm은 코드 작성을위한 뛰어난 IDE 일뿐만 아니라 코드베이스를 최신 버전의 PHP로 마이그레이션하는 데 도움이되는 정적 코드 분석 도구를 제공합니다. (작성자는 전체 코드 혹은 특정 디렉토리를 기준으로 정적 분석 도구를 사용했고 PhpStorm이 가장 많이 도움이 됐다고 합니다)
- 자동화 된 테스트를 통한 높은 적용 범위는 마이그레이션 프로세스를 크게 단순화합니다. (그럼요!)
- 새로운 주요 버전의 PHP로 업그레이드하는 것은 언뜻보기에 그리 어렵지 않습니다. (설마요!)
Do not mock what you do not own
https://thephp.cc/articles/do-not-mock-what-you-do-not-own
소유하지 않은 것은 mocking하지 말 것. 대체된 종속성을 제어하지 않으면, 다른 것도 제어가 안 되기 시작할 겁니다.
Named-entity recognition in PHP
https://www.we-rc.com/blog/2021/04/04/named-entity-recognition-in-php
RubixML을 사용하여 간단한 ML 문제를 해결하는 예입니다.
Using exceptions and retries when working with network services.
https://blog.frankdejonge.nl/back-the-func-off/
실패를 수용하는 추상 레이어 디자인을 소개합니다.
controller같은 사용자 레이어에서 아래와 같은 코드는 DatabaseException 같은 구현 세부 사항을 알아야 하기 때문에 추상화 누출
사고가 납니다.
try { |
아래 코드처럼 뒤에 어떤 구현이 있는지 몰라도 이해할 수 있게 Exception을 대체하는 방식을 소개합니다.
final class UnableToMarkCarUnavailable extends RuntimeException |
그리고 HTTP 기반 API는 광범위한 네트워크 관련 문제에 노출되기 때문에, 서비스 재시도 매커니즘을 두어야 한다고 말합니다. 이때 재시도 매커니즘을 사용자 레이어 안에 배치할지 구현 레이어 안에 배치할 지는 각각 장단점이 있습니다. 점진적으로 간격을 늘려주는 back-off 전략이 필요하다면 eventsauce/backoff 패키지를 사용할 수도 있습니다.
Algorithmic complexity (big O notation) of built-in PHP functions.
https://stackoverflow.com/questions/2473989/list-of-big-o-for-php-functions/2484455#2484455
내장 PHP 함수의 알고리즘 복잡성 (big O 표기법).
몇 가지 흥미로운 점
- isset / array_key_exists가 in_array / array_search 보다 훨씬 빠르다
- +(union)이 array_merge보다 훨씬 빠르다(보기도 좋다). 물론 동작 방식은 다르지만.
- shuffle은 array_rand와 동일한 Big-O tier에 존재한다.
- array_pop / array_push는 array_shift / array_unshift 보다 빠르다. 재 인덱스 때문.
참고로 2010에 쓴 답변입니다.
A look into the most popular packages on Packagist and their licences
https://blog.exussum.co.uk/licence.html
Packagist에서 가장 인기있는 패키지와 해당 라이선스 살펴보기. 많은 인기있는 패키지에는 라이선스가 없거나 잘못 설정되어 있습니다.
📺 Videos
Modern PHP with Rasmus Lerdorf
https://www.youtube.com/watch?v=Hc4S74LCXHo
PHP의 아버지가 약간의 Etsy의 코드와 PHP 8에 대해 이야기합니다.
Videos from Derick Rethans on Xdebug 3
- Xdebug with Docker and PhpStorm in 5 minutes
- Profiling with Xdebug in Docker
- Debugging Unit Tests with PhpStorm on Linux
🔈 Podcasts
PHP Ugly podcast:
• #236: – Memory Leaks.
• #235: – Ugly Hot Tub PHP Coding.
PHP Release Radar:
• Episode #9 – With Andreas Braun discussing Doctrine Cache 2.0.
PHP Internals News podcast:
• Episode #82 – About auto-capturing multi-statement closures (RFC) with Larry Garfield and Nuno Maduro.
• Episode #79 – About the new operator in initializers with Nikita Popov.
🙌 Community
PHP’s bus factor is 2
https://blog.krakjoe.ninja/2021/05/avoiding-busses.html
Joe Watkins는 PHP 소스에 대해 충분히 알고있는 사람은 두 사람뿐이므로 PHP에 새로운 기능을 추가 할 때이 점을 고려해야합니다. 그는 또한 코어에서 작업하는 더 많은 개발자가 필요하다고 말합니다.