PHP 8.3 – co nowego w najnowszej wersji PHP? Zmiany i nowości

PHP 8.3 - co nowego?

Jeśli interesujesz się rozwojem technologii webowych lub rozwijasz się jako programista, z pewnością ucieszy Cię wiadomość, że właśnie zostało wydane PHP 8.3! Ta najnowsza wersja jednego z najpopularniejszych języków programowania do tworzenia aplikacji internetowych przynosi ze sobą szereg innowacji i ulepszeń. W tym artykule przybliżymy, co dokładnie nowego oferuje aktualizacja PHP 8.3.

Wydanie PHP 8.3 to nie tylko kolejna aktualizacja — to kolejny krok na drodze ulepszania tego języka programowania, a także zwiększania jego wydajności. Nowe funkcje mogą znacząco wpłynąć na Twoje projekty i aplikacje. Jednak to nie wszystko. W tym artykule wyjaśnimy, oprócz zmian w PHP 8.3, jak aktualizacja PHP wpływa na bezpieczeństwo i wydajność Twoich aplikacji internetowych, a także, dlaczego warto zawsze — w miarę możliwości — korzystać z najnowszej wersji PHP.

Aktualizacja do PHP 8.3 to nie tylko dostęp do nowych narzędzi; to inwestycja w przyszłość i bezpieczeństwo Twoich aplikacji. 

Co to jest wersja PHP, czyli co musisz wiedzieć o języku PHP

Wersja PHP jest określeniem używanym do opisania konkretnego wydania języka programowania PHP. Każda wersja PHP zawiera określone ulepszenia, poprawki błędów i nowe funkcje. Dla osób, które tworzą i zarządzają stronami internetowymi, znajomość wersji PHP jest istotna ze względu na kompatybilność kodu.

Gdy pojawia się nowa wersja PHP, zmieniają się jednak nie tylko możliwości oraz reguły pisania kodu. Wydana zostaje także nowa wersja interpretera PHP, zgodna z aktualną wersją wytycznych. Interpreter PHP to właśnie ten element oprogramowania, który działa na serwerze i odczytuje oraz wykonuje kod strony napisany zgodny z aktualnymi standardami. Jak każde oprogramowanie, jest on na bieżąco aktualizowany, aby obsługiwał nowe wytyczne i standardy, a także działał wydajniej.

Dlaczego warto aktualizować PHP?

Nowe wersje PHP mogą wprowadzać zmiany w składni i funkcjonalności języka, co może mieć wpływ na działanie istniejącego kodu strony internetowej. Dlatego ważne jest, aby programiści i administratorzy stron internetowych byli świadomi różnic pomiędzy różnymi wersjami PHP i stale aktualizowali swoje aplikacje, aby uniknąć problemów z kompatybilnością i bezpieczeństwem. 

Usprawnienia wprowadzane w nowszych wersjach PHP wpływają jednak nie tylko na standardy pisania kodu, ale także na wydajność wspomnianego interpretera PHP. Przekłada się to na szybkość, z jaką strona internetowa działa i wykonuje swoje operacje. Innymi słowy, z reguły im nowsza wersja PHP, tym strona szybciej działa. Ponadto, starsze wersje PHP mogą mieć lukę bezpieczeństwa lub inne problemy, dlatego należy unikać korzystania z przestarzałych wersji PHP.

Ze względu na powyższe, zalecane jest aktualizowanie wersji PHP do najnowszej. Jeśli posiadasz stronę w LH.pl, możesz samodzielnie zmienić wersję PHP na swoim hostingu w panelu klienta. Zobacz, jak zmienić wersję PHP w LH.pl. 

Skoro wiemy już, jak wersja PHP wpływa na działanie strony internetowej oraz jej bezpieczeństwo, pora zająć się zmianami w najnowszej wersji PHP 8.3. 

Co nowego w PHP 8.3?

PHP 8.3 przynosi ze sobą imponujący zestaw nowości i ulepszeń, które mają na celu uczynienie Twojego kodowania jeszcze bardziej efektywnym i przyjemnym. Wśród najbardziej wyczekiwanych zmian znajdziemy między innymi usprawnienia w klasach tylko do odczytu (readonly classes), nową funkcję json_validate(), dodatki do niedawno wprowadzonej klasy Randomizer, wykrywanie przepełnienia stosu, a także wiele innych.

Zmiany dotyczące właściwości readonly

W PHP 8.3, wprowadzono pewną zmianę dotyczącą właściwości readonly (tylko do odczytu) w klasach. Wcześniej, gdy zadeklarowałeś właściwość jako readonly, nie mogłeś jej zmienić po utworzeniu obiektu. Jednak nowa zmiana pozwala na nadpisanie takiej właściwości, ale tylko w szczególnym przypadku: wewnątrz funkcji klonowania obiektu __clone().

// Klasa reprezentująca artykuł
readonly class Article
{
    // Data publikacji artykułu, tylko do odczytu
    public function __construct(
        public DateTime $publishedDate,
    ) {}

   // Funkcja klonująca
    public function __clone()
    {
        // Przypisanie nowej daty do sklonowanego artykułu
        $this->publishedDate = new DateTime();
    }
}

Funkcja json_validate()

W PHP 8.3 wprowadzono nową funkcję o nazwie json_validate(), która służy do walidacji danych w formacie JSON. Poprzednio, aby sprawdzić, czy dane JSON są poprawne, do dyspozycji były różne metody, takie jak:

  • konfiguracja flagi JSON_THROW_ON_ERROR,
  • użycie json_last_error,
  • sprawdzenie, czy json_decode() zwraca null.

Nowa funkcja json_validate() znacznie upraszcza ten proces. Pozwala ona sprawdzić, czy podany ciąg znaków w formacie JSON jest poprawny, zwracając true dla poprawnych danych JSON i false dla niepoprawnych. Dodatkowo, jeśli JSON jest niepoprawny, możesz użyć json_last_error_msg() i json_last_error(), aby dowiedzieć się więcej o błędzie.

Określanie typu stałych klasowych

Wprowadzenie stałych typowanych w PHP 8.3 to znacząca zmiana, która pomaga unikać niejasności dotyczących typów danych używanych w stałych (const). W poprzednich wersjach PHP, typ stałej nie był jasno określony, co mogło prowadzić do błędów i nieporozumień.

Przykład problemu w starszych wersjach PHP:

interface Configurable {
    const SETTINGS = ["theme" => "dark"]; // Zakładamy, że SETTINGS to zawsze tablica
}

class WebPage implements Configurable {
    const SETTINGS = "light"; // Ale tutaj SETTINGS to ciąg znaków
}

class MobilePage extends WebPage {
    const SETTINGS = 42; // A tutaj SETTINGS to liczba
}

Na powyższych przykładach widzimy, że w zależności od miejsca, przypisaliśmy inny typ wartości do danej stałej.

W PHP 8.3, możemy wyraźnie określić typ stałej, co sprawia, że kod staje się bardziej przewidywalny i bezpieczny.

Nowy przykład w PHP 8.3:

interface Configurable {
    const array SETTINGS = ["theme" => "dark"]; // Jawnie określamy, że SETTINGS jest tablicą
}

class WebPage implements Configurable {
    const array SETTINGS = ["theme" => "light"]; // WebPage::SETTINGS musi być tablicą
}

class MobilePage extends WebPage {
    const array SETTINGS = ["theme" => "mobile", "size" => "small"]; // MobilePage::SETTINGS również musi być tablicą, ale możemy zmienić jej wartości
}

// Przykład błędu

// Fatal error: Cannot use string as value for class constant
// WebPage::SETTINGS of type array
class ErrorPage implements Configurable {
    const array SETTINGS = "error"; // Błąd: SETTINGS musi być tablicą, a nie ciągiem znaków
}

W tym przykładzie, poprzez deklarowanie stałych jako typowanych (np. const array SETTINGS), zapewniamy, że każda implementacja interfejsu Configurable oraz dziedziczenie klas będzie przestrzegać zadeklarowanego typu stałej, unikając tym samym potencjalnych błędów.

Atrybut #[Override] w PHP 8.3

Atrybut #[Override] w PHP 8.3 jest nowością, która służy do wskazywania, że dana metoda w klasie dziedziczącej nadpisuje metodę z klasy bazowej. Jest to szczególnie przydatne, gdy chcemy być pewni, że nasza metoda nadal nadpisuje metodę rodzica, nawet jeśli w klasie bazowej dojdzie do zmian.

Przykład użycia atrybutu #[Override]:

abstract class Vehicle
{
    public function startEngine(): string
    {
        return "Engine started";
    }
}

final class Car extends Vehicle
{
    #[Override]
    public function startEngine(): string
    {
        return "Car engine started"; // Nadpisana metoda
    }
}

Teraz, wyobraźmy sobie sytuację, w której metoda w klasie bazowej Vehicle zmienia nazwę:

abstract class Vehicle
{
    public function igniteEngine(): string
    {
        return "Engine started";
    }
}

Dzięki atrybutowi #[Override], PHP wykryje, że metoda startEngine() w klasie Car już nie nadpisuje żadnej metody z klasy bazowej Vehicle i zgłosi błąd.

Atrybut #[Override] jest przydatnym narzędziem do zapewnienia, że nasz kod zachowuje spójność, szczególnie w dużych i skomplikowanych projektach, gdzie zmiany w klasach bazowych mogą nie być od razu zauważone w klasach dziedziczących.

Negatywne indeksy w tablicach (array)

W PHP 8.3 wprowadzono zmianę dotyczącą zachowania indeksów negatywnych w tablicach. W poprzednich wersjach PHP, gdy dodawałeś element do tablicy z użyciem negatywnego indeksu, a następnie dodawałeś kolejny element bez określenia indeksu, ten drugi element otrzymywał zawsze indeks 0. W PHP 8.3 to zachowanie zostało zmienione.

Przykład w PHP przed wersją 8.3:

$myArray = [];

$myArray[-3] = 'pierwszy';
$myArray[] = 'drugi';

var_export($myArray);

// Wynik w starszych wersjach PHP:
// array (
//   -3 => 'pierwszy',
//   0 => 'drugi',
// )

W tym przykładzie, po dodaniu ‘pierwszy’ pod indeksem -3, dodanie ‘drugi’ bez określenia indeksu powoduje przypisanie mu indeksu 0.

Teraz zobaczmy, jak działa to w PHP 8.3:

$myArray = [];

$myArray[-3] = 'pierwszy';
$myArray[] = 'drugi';

var_export($myArray);

// Wynik w PHP 8.3:
// array (
//   -3 => 'pierwszy',
//   -2 => 'drugi',
// )

W PHP 8.3, ‘drugi’ element zostaje automatycznie przypisany do następnego dostępnego negatywnego indeksu, w tym przypadku -2, co jest kontynuacją od ostatniego użycia negatywnego indeksu. Ta zmiana sprawia, że zarządzanie tablicami z użyciem negatywnych indeksów jest bardziej przewidywalne i spójne.

Dynamiczny dostęp do stałych klas

Zmiana w PHP 8.3 dotycząca dynamicznego dostępu do stałych klas jest znacząca. W poprzednich wersjach PHP (>= 8.2), jedyną możliwością pobrania wartości stałej klasy dynamicznie było użycie funkcji constant(). Natomiast w PHP 8.3 wprowadzono możliwość bezpośredniego dostępu do stałych klas w sposób dynamiczny.

Przykład w PHP przed wersją 8.3:

class Book {
    const TITLE = '1984';
}

$constName = 'TITLE';

// Możliwe tylko za pomocą funkcji constant()
echo constant(Book::class . '::' . $constName); // Wypisze '1984'

// Poniższe spowodowałoby błąd składni w PHP >= 8.2.0
// echo Book::{$constName};
// ParseError: syntax error, unexpected token ";", expecting "(".

W tym przykładzie, próba dynamicznego dostępu do stałej klasy Book::TITLE za pomocą składni Book::{$constName} spowodowałaby błąd składni w PHP 8.2 i wcześniejszych wersjach.

Teraz zobaczmy, jak to działa w PHP 8.3:

class Book {
    const TITLE = '1984';
}

$constName = 'TITLE';

// Teraz można dynamicznie uzyskać dostęp do stałej klasy
echo Book::{$constName}; // Wypisze '1984'

W PHP 8.3, składnia Book::{$constName} jest już poprawna i umożliwia dynamiczne odwoływanie się do stałej TITLE w klasie Book. Ta zmiana sprawia, że praca z klasami i ich stałymi staje się bardziej elastyczna i wydajna.

Anonimowe klasy readonly

W PHP 8.3 wprowadzono znaczącą zmianę, pozwalającą na oznaczanie anonimowych klas jako readonly. W poprzednich wersjach PHP nie było to możliwe, co ograniczało elastyczność i możliwości zastosowania anonimowych klas w niektórych scenariuszach.

Oto spersonalizowany przykład ilustrujący tę nową funkcjonalność:

Przykład przed PHP 8.3:

// Tworzenie anonimowej klasy
$vehicle = new class {
    public function __construct(
        public string $type = 'Car',
        public string $color = 'Red'
    ) {}
};

// W PHP przed 8.3 nie można było użyć readonly w anonimowych klasach.

W tym przykładzie, próba oznaczenia anonimowej klasy jako readonly nie byłaby możliwa.

Teraz zobaczmy zmianę w PHP 8.3:

// Tworzenie anonimowej klasy jako readonly w PHP 8.3
$vehicle = new readonly class {
    public function __construct(
        public string $type = 'Car',
        public string $color = 'Red'
    ) {}
};

// Teraz możemy tworzyć anonimowe klasy jako readonly.

W PHP 8.3, możemy tworzyć anonimowe klasy z oznaczeniem readonly, co pozwala na większą kontrolę nad modyfikowalnością właściwości obiektu. To ulepszenie przyczynia się do lepszego zarządzania stanem obiektów i zwiększa bezpieczeństwo kodu poprzez zapobieganie niezamierzonej modyfikacji właściwości.

Domyślne wartości dla zmiennych środowiskowych

W PHP 8.3 wprowadzono bardzo przydatną funkcję umożliwiającą określenie domyślnej wartości dla zmiennych środowiskowych używanych przy definiowaniu ustawień w plikach INI. Załóżmy, że pracujesz nad aplikacją, która korzysta z serwera FPM do obsługi żądań. Chcesz skonfigurować port nasłuchiwania serwera FPM w pliku konfiguracyjnym INI, ale także zapewnić domyślną wartość, na wypadek gdyby zmienna środowiskowa nie została zdefiniowana.

Przed PHP 8.3, konfiguracja w pliku INI mogłaby wyglądać tak:

[server]
listen = localhost:${MY_APP_FPM_PORT}

W tej konfiguracji, jeśli zmienna środowiskowa MY_APP_FPM_PORT nie jest zdefiniowana, konfiguracja nie będzie mieć określonej wartości dla portu nasłuchiwania, co może prowadzić do problemów.

Teraz, w PHP 8.3, możesz dodać domyślną wartość:

[server]
listen = localhost:${MY_APP_FPM_PORT:-8080}

W tym przypadku, jeśli zmienna MY_APP_FPM_PORT nie jest zdefiniowana, domyślnie zostanie użyta wartość 8080. To sprawia, że konfiguracja staje się bardziej elastyczna i niezawodna, ponieważ zapewnia sensowną wartość domyślną, która może być użyta, gdy zmienna środowiskowa nie jest dostępna.

Ten przykład pokazuje, jak nowa funkcja w PHP 8.3 może uprościć zarządzanie konfiguracjami w różnych środowiskach, szczególnie w kontekście konteneryzacji, jak w przypadku Docker. Dzięki temu rozwiązaniu nie musisz polegać wyłącznie na blokach ENV w Dockerfile do określania wartości domyślnych.

Rozszerzenia dla klasy Randomizer

W PHP 8.3, klasa Randomizer, która została wprowadzona w PHP 8.2, została rozszerzona o nowe funkcje. Te dodatki ułatwiają generowanie losowych danych w różnych formatach. Oto spersonalizowane przykłady wykorzystania tych nowych funkcji:

Randomizer::getBytesFromString(string $string, int $length): string

Ta metoda pozwala na generowanie ciągu o określonej długości, składającego się z losowo wybranych bajtów z podanego ciągu.

Przykład:

$randomizer = new Randomizer();

$sourceString = "abcdef123456";
$length = 4;

$randomBytes = $randomizer->getBytesFromString($sourceString, $length);

echo $randomBytes; // Wyświetla ciąg o długości 4, zawierający losowo wybrane znaki z $sourceString

Randomizer::getFloat(float $min, float $max, IntervalBoundary $boundary = IntervalBoundary::ClosedOpen): float

Metoda getFloat() zwraca losową liczbę zmiennoprzecinkową pomiędzy $min a $max. Dzięki parametrowi IntervalBoundary, możesz określić, czy wartości graniczne mają być włączone do zakresu (Closed) czy wyłączone (Open).

Przykład:

$randomizer = new Randomizer();

$min = 0.5;
$max = 2.5;

$randomFloat = $randomizer->getFloat($min, $max, IntervalBoundary::ClosedOpen);

echo $randomFloat; // Wyświetla losową wartość zmiennoprzecinkową pomiędzy 0.5 (włącznie) a 2.5 (wyłącznie)

Randomizer::nextFloat(): float

nextFloat() to skrócona forma getFloat(0, 1, IntervalBoundary::ClosedOpen), co oznacza, że zwraca losową liczbę zmiennoprzecinkową między 0 a 1, gdzie 1 jest wyłączone.

Przykład:

$randomizer = new Randomizer();

$randomFloat = $randomizer->nextFloat();

echo $randomFloat; // Wyświetla losową wartość zmiennoprzecinkową pomiędzy 0 (włącznie) a 1 (wyłącznie)

Te nowe metody w klasie Randomizer znacznie poszerzają możliwości generowania losowych danych w PHP, co jest przydatne w wielu różnych scenariuszach programistycznych, od testowania po generowanie unikalnych identyfikatorów sesji.

Bardziej odpowiednie wyjątki związane z datami i czasami

W PHP 8.3 wprowadzono nowe, bardziej odpowiednie wyjątki związane z datami i czasami, zastępując ogólne wyjątki i błędy, które były wcześniej używane. Te dedykowane wyjątki umożliwiają dokładniejsze i bardziej celowane obsługiwanie błędów w kodzie związanym z datami i czasami.

Spersonalizowane przykłady zastosowania nowych wyjątków:

DateMalformedIntervalStringException

Ten wyjątek jest wyrzucany, gdy podany ciąg znaków dla DateInterval jest błędny lub niepoprawny.

Przykład:

try {
    $interval = new DateInterval('niepoprawny ciąg');
} catch (DateMalformedIntervalStringException $e) {
    echo "Błąd: Niepoprawny ciąg dla DateInterval.";
}

DateInvalidOperationException

Ten wyjątek jest wyrzucany, na przykład, gdy próbujemy wykonać niedozwoloną operację, jak odjęcie specyfikacji czasu względnego.

Przykład:

$date = new DateTime();

try {
    $date->sub(new DateInterval('PT30M')); // Załóżmy, że operacja jest niedozwolona
} catch (DateInvalidOperationException $e) {
    echo "Błąd: Operacja na DateTime jest niedozwolona.";
}

DateRangeError

DateRangeError jest wyjątkiem wyrzucanym na platformach 32-bitowych, gdy epoka nie mieści się w zakresie integera w PHP.

Przykład:

try {
    $date = new DateTime('@' . PHP_INT_MAX);
} catch (DateRangeError $e) {
    echo "Błąd: Data poza zakresem.";
}

Te nowe wyjątki poprawiają czytelność i dokładność obsługi błędów związanych z datami i czasami w PHP, umożliwiając bardziej precyzyjne reakcje na konkretne problemy. Warto jednak pamiętać, że te zmiany mogą wprowadzić pewne niekompatybilności w starszym kodzie, zwłaszcza na platformach 32-bitowych oraz w przypadku specyficznych operacji na datach.

Ulepszenie w obsłudze błędów dla funkcji unserialize()

W PHP 8.3 wprowadzono ulepszenie w obsłudze błędów dla funkcji unserialize(). Teraz, zamiast czasami generować ostrzeżenie typu E_NOTICE, funkcja ta będzie zawsze emitować ostrzeżenie E_WARNING w przypadku napotkania problemów.

To ulepszenie sprawia, że obsługa błędów jest bardziej spójna i widoczna, co pomaga w debugowaniu i utrzymaniu kodu.

Oto przykład, ilustrujący tę zmianę w obsłudze błędów. Załóżmy, że mamy serializowany ciąg znaków reprezentujący obiekt, ale ciąg ten został uszkodzony lub jest niekompletny:

$serializedObject = 'O:8:"MyObject":1:{s:5:"value";s:5:"Hello";}'; // Uszkodzony lub niekompletny ciąg

try {
    $object = unserialize($serializedObject);
} catch (Exception $e) {
    echo "Wystąpił wyjątek: " . $e->getMessage();
}

// W PHP przed 8.3, to mogłoby generować E_NOTICE.
// W PHP 8.3, zawsze generuje E_WARNING.

W tym przykładzie, jeśli unserialize() napotka problem z uszkodzonym ciągiem, zamiast generować E_NOTICE, co mogłoby zostać przeoczone w niektórych konfiguracjach logowania błędów, funkcja ta zawsze wygeneruje ostrzeżenie E_WARNING. To ułatwia wykrywanie i rozwiązywanie problemów związanych z deserializacją danych.

Warto zauważyć, że część proponowanych zmian RFC dotycząca dodania więcej wyjątków podczas działania unserialize() nie została zaakceptowana. Oznacza to, że w praktyce nadal należy polegać na tradycyjnych mechanizmach obsługi błędów, takich jak kontrola wartości zwracanej i obsługa ostrzeżeń.

Zmieniono zachowanie funkcji array_sum() i array_product()

W PHP 8.3, zmieniono zachowanie funkcji array_sum() i array_product(), aby były bardziej spójne z ich odpowiednikami zaimplementowanymi w przestrzeni użytkownika za pomocą funkcji array_reduce().

Zmiany i ich wpływ:

  1. Spójne zachowanie z array_reduce(): array_sum() i array_product() będą teraz działać tak samo jak ich warianty zaimplementowane za pomocą array_reduce(). Oznacza to, że zamiast pomijać elementy tablicy będące obiektami lub tablicami, te funkcje będą teraz wyrzucać TypeError.
  2. Emitowanie ostrzeżenia E_WARNING dla niekompatybilnych typów: Gdy funkcje napotkają typy danych, które nie są kompatybilne (np. ciągi znaków w array_product()), będą generować ostrzeżenie E_WARNING.
  3. Wsparcie dla obiektów z numerycznym rzutowaniem: Funkcje będą teraz wspierać obiekty, które mogą być rzutowane na wartości numeryczne (np. poprzez implementację metody __toString() zwracającej wartość numeryczną), umożliwiając ich dodawanie lub mnożenie.

Przykład:

$array = [2, 4, new MyClass(), 8];

try {
    $sum = array_sum($array);
    $product = array_product($array);
} catch (TypeError $e) {
    echo "Błąd: Niekompatybilny typ danych w tablicy.";
}

// Przed PHP 8.3, obiekt w tablicy zostałby pominięty.
// W PHP 8.3, powyższy kod spowoduje TypeError.

W tym przykładzie, jeśli klasa MyClass nie może być rzutowana na wartość numeryczną, array_sum() i array_product() w PHP 8.3 wyrzucą wyjątek TypeError, w przeciwieństwie do starszych wersji PHP, gdzie obiekt zostałby pominięty.

Te zmiany wprowadzają większą konsekwencję w zachowaniu tych funkcji oraz lepszą obsługę błędów, co pomaga w unikaniu subtelnych błędów i nieoczekiwanych zachowań w kodzie.

Naprawiono błąd w widoczności stałych w interfejsach

W PHP 8.3 naprawiono błąd związany z widocznością stałych w interfejsach, co może prowadzić do przerwania kompatybilności w niektórych przypadkach. Wcześniej, PHP nie sprawdzał zgodności widoczności stałych podczas implementacji interfejsu. W PHP 8.3 ta zgodność jest teraz egzekwowana, co oznacza, że stałe w klasie implementującej interfejs muszą mieć co najmniej taką samą widoczność, jak stałe zadeklarowane w interfejsie.

Zmiana i jej wpływ:

Wcześniej w PHP, mogłeś zadeklarować stałą w interfejsie jako publiczną, a następnie przesłonić ją w klasie implementującej ten interfejs przy użyciu mniejszej widoczności (np. private). Teraz, w PHP 8.3, taka operacja spowoduje błąd.

Przykład:

Przed PHP 8.3:

interface I {
    public const FOO = 'foo';
}

class C implements I {
    private const FOO = 'foo'; // To było dozwolone wcześniej
}

W PHP 8.3, próba zadeklarowania private const FOO w klasie C, która implementuje interfejs I z public const FOO, spowoduje błąd. Poprawny kod powinien wyglądać następująco:

interface I {
    public const FOO = 'foo';
}

class C implements I {
    public const FOO = 'foo'; // Widoczność musi być zgodna z deklaracją w interfejsie
}

To ulepszenie pomaga zapewnić spójność i przewidywalność w zakresie widoczności stałych w interfejsach i klasach implementujących te interfejsy. Jednakże, może to wymagać modyfikacji istniejącego kodu w niektórych projektach, aby zapewnić zgodność z nowym wymogiem PHP 8.3.

Zmiana sposobu, w jaki traktowane są statyczne właściwości w traitach

W PHP 8.3 wprowadzono zmianę dotyczącą sposobu, w jaki traktowane są statyczne właściwości w traitach.

W poprzednich wersjach PHP, gdy klasa używała traitu zawierającego statyczną właściwość, ta właściwość była współdzielona między wszystkimi klasami używającymi tego traitu. Teraz, w PHP 8.3, użycie statycznej właściwości w trait sprawi, że zostanie ona zadeklarowana na nowo w każdej klasie używającej tego traitu, tworząc oddzielne miejsce przechowywania dla statycznej właściwości w każdej z tych klas.

Nowa funkcja mb_str_pad()

W PHP 8.3 wprowadzono nową funkcję mb_str_pad(), która jest odpowiednikiem str_pad() dla stringów wielobajtowych. To ważne ulepszenie, zwłaszcza przy pracy z językami i znakami, które wykorzystują kodowanie wielobajtowe, takie jak UTF-8.

mb_str_pad() pozwala na uzupełnienie stringa do określonej długości za pomocą innego stringa. Jest to szczególnie przydatne, gdy pracujemy z tekstem w kodowaniu wielobajtowym, gdzie zwykła funkcja str_pad() może nie działać poprawnie ze względu na różną długość bajtów reprezentujących znaki.

Funkcja wygląda następująco:

function mb_str_pad(
    string $string, 
    int $length, 
    string $pad_string = " ", 
    int $pad_type = STR_PAD_RIGHT, 
    ?string $encoding = null
): string {}

Parametry:

  • $string: String, który ma być uzupełniony.
  • $length: Docelowa długość stringa po uzupełnieniu.
  • $pad_string: String używany do uzupełnienia $string (domyślnie spacja).
  • $pad_type: Typ uzupełnienia (STR_PAD_RIGHT, STR_PAD_LEFT, STR_PAD_BOTH).
  • $encoding: Opcjonalny parametr określający kodowanie znaków (np. “UTF-8”).

Przykład użycia:

$string = "こんにちは"; // Japońskie powitanie "konnichiwa"
$paddedString = mb_str_pad($string, 10, "_", STR_PAD_BOTH, "UTF-8");

echo $paddedString; // Wyświetli string uzupełniony podkreślnikami do 10 znaków

W tym przykładzie, mb_str_pad() uzupełnia string “こんにちは” do długości 10 znaków, używając podkreślników i centrując tekst. Dzięki obsłudze UTF-8, każdy japoński znak jest poprawnie traktowany jako pojedynczy znak, co zapewnia prawidłowe uzupełnienie.

Dodanie mb_str_pad() do PHP 8.3 znacznie ułatwia pracę z tekstami w różnych językach i kodowaniach, eliminując problemy związane z niewłaściwym uzupełnianiem stringów wielobajtowych.

Artykuł odpowiedział na twoje pytanie? Udostępnij go dalej:
Obrazek domyślny
Błażej Starosta
Ma doświadczenie w tworzeniu oraz prowadzeniu stron WWW, od blogów aż po sklepy internetowe. Od lat uważnie śledzi rozwój WordPressa i jego wpływ na rynek twórców stron internetowych. Stara się być na bieżąco ze wszystkimi nowinkami technologicznymi i dzielić się swoją wiedzą.