Co nowego w PHP 8.4
Po roku prac przedstawiono wydanie języka programowania PHP 8.4. Nowa wersja zawiera serię nowych możliwości oraz kilka zmian powodujących niezgodność wsteczną.
Kluczowe zmiany w PHP 8.4
- Zaproponowano nową implementację kompilatora JIT zbudowaną w oparciu o Framework IR. Kluczowa różnica polega na tym, że stary JIT bezpośrednio generował instrukcje maszynowe w oparciu o bajtkod, używając różnych backendów dla architektur x86_64 i AArch64, podczas gdy nowy JIT wykorzystuje jeden backend dla wszystkich architektur i generuje reprezentację pośrednią (IR), która następnie jest dodatkowo optymalizowana i przekształcana w instrukcje maszynowe dla docelowej platformy.
- Dodano obsługę zaczepek właściwości (property hook), pozwalających na dodanie dodatkowej logiki wykonywanej przy zmianie lub dostępie do właściwości obiektu, implementowanej bez перехвату operacji odczytu i zapisu za pomocą wspólnych funkcji __get i __set oraz bez tworzenia dodatkowych metod-obwódek. Użycie zaczepek właściwości umożliwia znaczne skrócenie kodu i uproszczenie redefinicji zachowania pracy z właściwościami poprzez przywiązanie własnej procedury obsługi do każdej właściwości.
class User
{
public string $name {
set {
if (strlen($value) === 0) {
throw new ValueError("Name must be non-empty");
}
$this->name = $value;
}
}
public function __construct(string $name) {
$this->name = $name;
}
}
- Zezwolono na wskazywanie referencji do metod w konstruktorze "new" bez nawiasów rozdzielających, tj. zamiast "$name = (new MyClass())->method()" można teraz pisać "$name = new MyClass()->method()".
- Dodano możliwość asymetrycznego zarządzania widocznością właściwości obiektów (public, private, protected), osobno dla operacji zapisu (set) i odczytu (get). Na przykład:
class PhpVersion
{
public private(set) string $version = '8.4';
}
$phpVersion = new PhpVersion();
var_dump($phpVersion->version); // string(3) "8.4"
$phpVersion->version = 'PHP 8.3'; // error
- Wprowadzono natywne wsparcie dla "leniwych" obiektów (lazy), których inicjalizacja następuje w momencie pierwszego użycia.
- Zamiast ogólnego parametru "opcache.jit_buffer_size" do zarządzania kompilatorem JIT i konfiguracji rozmiaru bufora JIT, zaproponowano parametry "opcache.jit" i "opcache.jit_buffer_size". Aby wyłączyć JIT, można teraz wskazać "opcache.jit=disable" zamiast "opcache.jit_buffer_size=0". Wprowadzono zmiany zmniejszające zużycie pamięci i poprawiające wydajność JIT w niektórych sytuacjach.
- Dodano atrybut "#[\Deprecated]" przeznaczony do oznaczania przestarzałych funkcji, klas i metod.
#[\Deprecated("use newFunction() instead", since: "1.1")]
function oldFunction() {
// …
}
- Zrealizowano klasę \Dom\HTMLDocument, obsługującą poprawne parsowanie znaczników HTML5.
- Dodano funkcję request_parse_body() do parsowania żądań HTTP z typem treści multipart/form-data (RFC1867).
- Dodano funkcje array_find(), array_find_key(), array_any() i array_all(). Funkcje array_find() i array_find_key() zwracają pierwszy element lub klucz w tablicy, dla których sprawdzenie zadane przez callback użytkownika zwróciło true. Z kolei funkcje array_any() i array_all() zwracają dowolny pasujący element i wszystkie pasujące elementy. Na przykład, aby wyświetlić pierwszy element, którego pole title ma długość powyżej 5 znaków, można wskazać:
$firstMatch = array_find(
$posts,
function (Post $post) {
return strlen($post->title) > 5;
}
);
- Dodano metody DateTime::getMicrosecond() i DateTimeImmutable::setMicrosecond($microsecond) do pobierania i ustawiania czasu z dokładnością do mikrosekundy, a także metodę DateTime::createFromTimestamp().
- W PDO (PHP Data Objects), abstrakcyjnym interfejsie do pracy z bazami danych, dodano możliwość tworzenia parserów SQL i podklas specyficznych dla określonych sterowników baz danych. Dodano nowe podklasy Pdo\Dblib, Pdo\Firebird, Pdo\MySql, Pdo\Odbc i Pdo\Sqlite.
- Dodano nowe funkcje: mb_trim(), mb_ltrim(), mb_rtrim(), mb_ucfirst(), mb_lcfirst(), bcceil(), bcdivmod(), bcfloor(), bcround(), pcntl_getcpu(), pcntl_getcpuaffinity(), pcntl_getqos_class(), pcntl_setns(), pcntl_waitid(), http_get_last_response_headers(), http_clear_last_response_headers(), fpow().
- Operacje exit i die można teraz wywoływać w formie pełnoprawnych funkcji, które można przekazywać jako argument do innych funkcji. Wcześniej możliwości funkcji exit() i die() były mocno ograniczone, ponieważ były to obwódki słów kluczowych exit i die.
- Dodano zmiany utrudniające eksploatację podatności spowodowanych przepełnieniem bufora oraz wzmacniające losowość nazw plików tworzonych przez funkcję tempnam().
- Ogłoszono jako przestarzałe zachowanie, w którym dla parametrów funkcji z domyślną wartością null automatycznie zezwalano na przypisanie wartości null. Aby takie parametry mogły przyjmować wartości null, teraz wymagane jest jawne wskazanie prefiksu "?". Na przykład, zamiast "function save(Book $book = null) {}" należy wskazywać "function save(?Book $book = null) {}".
- Ogłoszono jako przestarzałe stałe E_STRICT, MYSQLI_REFRESH_*, funkcje mysqli_ping(), mysqli_kill(), mysqli_refresh(), metody mysqli::ping(), mysqli::kill(), mysqli::refresh(), możliwość używania "_" jako nazwy klasy, niektóre właściwości DOMDocument i DOMEntity. Zakazano przedefiniowywania stałych klasy GMP, dla którego teraz ustawiono słowo kluczowe "final".
Dodatkowo można zauważyć wydanie statycznego analizatora PHPStan 2.0, pozwalającego na znajdowanie błędów w kodzie PHP bez jego wykonywania i używania testów jednostkowych. Analizator zapewnia 10 poziomów, obejmujących takie obszary jak: wykrywanie niezdefiniowanych zmiennych, nieznanych klas, funkcji i metod; sprawdzanie typów argumentów i wartości zwracanych; poprawność użycia niektórych typów; określanie nigdy nie wywoływanego kodu. Kod projektu jest napisany w PHP i dystrybuowany na licencji MIT.