Nowości w PHP 8.3 - Typed Class Constants, Override Attribute i json_validate()
PHP 8.3, wydany 23 listopada 2023 roku, wprowadza kolejne udoskonalenia zwiększające bezpieczeństwo typów i czytelność kodu. Najważniejsze nowości to typowane stałe klas, atrybut #[Override], funkcja json_validate() oraz dynamiczne pobieranie stałych klas.
Dlaczego PHP 8.3?
PHP 8.3 kontynuuje trend zwiększania bezpieczeństwa typów i eliminowania potencjalnych błędów. Wprowadza funkcje, które czynią kod bardziej jawnym, łatwiejszym do utrzymania i mniej podatnym na błędy.
1. Typed Class Constants - Typowane Stałe Klas
PHP 8.3 pozwala na deklarowanie typów dla stałych klas, interfejsów, traitów i enumów. Wspierane są wszystkie typy PHP (poza void, callable i never). Sprawdzanie typów jest zawsze strict, niezależnie od declare(strict_types=1).
<?php
interface Repository
{
public const string TABLE_NAME = 'users';
public const int MAX_RESULTS = 100;
public const array ALLOWED_FIELDS = ['id', 'name', 'email'];
}
class UserRepository implements Repository
{
// Musi zachować kompatybilność typu (kowariantność)
public const string TABLE_NAME = 'app_users';
public const int MAX_RESULTS = 50;
// Error - niezgodny typ
// public const string MAX_RESULTS = '50'; // Fatal error
}
class Config
{
public const string APP_NAME = 'MyApp';
public const string|null API_KEY = null;
public const array<string> FEATURES = ['auth', 'api', 'admin'];
// Finalne stałe nie mogą być nadpisane
final public const string VERSION = '1.0.0';
}
// Reflection API
$reflection = new ReflectionClassConstant(Config::class, 'APP_NAME');
$reflection->hasType(); // true
$reflection->getType()->getName(); // 'string'
2. Override Attribute - Atrybut #[Override]
Atrybut #[Override] jawnie sygnalizuje, że metoda nadpisuje metodę z klasy rodzica lub interfejsu. PHP zgłosi błąd, jeśli taka metoda nie istnieje w klasie nadrzędnej, co chroni przed błędami literówek i zmianami w API.
<?php
abstract class BaseController
{
abstract public function handle(): Response;
public function authorize(): bool
{
return true;
}
}
class UserController extends BaseController
{
// Jawnie deklarujemy nadpisanie
#[\Override]
public function handle(): Response
{
return new Response('Users list');
}
// Jeśli metoda nie istnieje w parent - Fatal error
#[\Override]
public function authrize(): bool // literówka!
{
return $this->user->isAdmin();
}
// Fatal error: UserController::authrize() has #[\Override] attribute,
// but no matching parent method exists
}
// Szczególnie przydatne przy zmianach w API
interface EventHandlerInterface
{
public function handle(Event $event): void;
}
class UserEventHandler implements EventHandlerInterface
{
#[\Override]
public function handle(Event $event): void
{
// Gdyby EventHandlerInterface zmienił nazwę metody,
// PHP natychmiast zgłosi błąd
}
}
3. json_validate() - Szybka Walidacja JSON
Nowa funkcja json_validate() pozwala na szybką walidację poprawności JSON bez parsowania całej struktury. Jest znacznie szybsza niż json_decode() gdy potrzebujesz tylko sprawdzić poprawność.
<?php
$json = '{"name": "Jan", "email": "jan@example.com"}';
// PHP 8.3 - szybka walidacja
if (json_validate($json)) {
echo "Valid JSON";
}
// PHP 8.2 - trzeba było parsować
json_decode($json);
if (json_last_error() === JSON_ERROR_NONE) {
echo "Valid JSON";
}
// Opcje walidacji (tak jak w json_decode)
$json = '{"name": "Jan", "email": "jan@example.com",}'; // trailing comma
json_validate($json, flags: JSON_INVALID_UTF8_IGNORE); // false
// Przydatne przy walidacji dużych plików
function validateJsonFile(string $path): bool
{
$content = file_get_contents($path);
return json_validate($content);
}
// Performance: json_validate() jest ~2x szybsze niż json_decode()
// dla dużych plików JSON
4. Dynamiczne Pobieranie Stałych Klas
PHP 8.3 pozwala na dynamiczne pobieranie stałych klas używając składni z nawiasami klamrowymi, podobnie jak przy dynamicznych właściwościach.
<?php
class Config
{
public const string DATABASE_HOST = 'localhost';
public const int DATABASE_PORT = 3306;
public const string DATABASE_NAME = 'myapp';
}
// Dynamiczne pobieranie stałej
$constantName = 'DATABASE_HOST';
$value = Config::{$constantName}; // 'localhost'
// Przydatne w pętlach
$constants = ['DATABASE_HOST', 'DATABASE_PORT', 'DATABASE_NAME'];
foreach ($constants as $const) {
echo "$const: " . Config::{$const} . "\n";
}
// Praktyczny przykład - konfiguracja z ENV
class Environment
{
public const string DEV = 'development';
public const string PROD = 'production';
public const string TEST = 'testing';
public static function get(): string
{
$env = $_ENV['APP_ENV'] ?? 'DEV';
return self::{$env}; // Dynamiczne pobranie
}
}
5. Randomizer::getBytesFromString()
Nowa metoda w klasie Randomizer pozwala na generowanie losowych stringów z podanego zestawu znaków w sposób kryptograficznie bezpieczny.
<?php
$randomizer = new \Random\Randomizer();
// Generowanie losowego kodu alfanumerycznego
$code = $randomizer->getBytesFromString(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
length: 16
);
// np. "aB3kL9mPqR2tYvW1"
// Token tylko z wielkich liter i cyfr
$token = $randomizer->getBytesFromString(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
length: 8
);
// np. "K3LP9M2Y"
// PIN code
$pin = $randomizer->getBytesFromString('0123456789', length: 6);
// np. "847293"
Inne ważne nowości w PHP 8.3
- Negative indices in arrays - negatywne indeksy do odwoływania się od końca tablicy
- Anonymous readonly classes - klasy anonimowe mogą być readonly
- New mb_str_pad() function - multibyte-safe str_pad()
- Improved unserialize() error handling - lepsze komunikaty błędów
🎓 Chcesz poznać wszystkie nowości PHP?
Ten wpis to fragment kompleksowego kursu PHP 8.4, w którym szczegółowo omawiam wszystkie wersje PHP 8.x wraz z praktycznymi przykładami z rzeczywistych projektów.