Gettery nie znikają. Część z nich po prostu przestaje mieć sens.
PHP 8.4 wprowadziło property hooks i asymmetric visibility. Skraca klasy, w których od lat powtarzałeś to samo: prywatne pole, publiczny getter, setter z trim i walidacją.
Jeśli nadal jesteś na 8.3, te dwie rzeczy często wystarczają jako powód do upgrade’u.
Property hooks w skrócie
Hook podpinasz pod odczyt albo zapis właściwości. IDE i static analysis widzą to jako właściwość, nie jako parę magicznych metod schowanych w __get.
final class Email
{
public string $value {
set(string $value) {
$normalized = strtolower(trim($value));
if (!filter_var($normalized, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email');
}
$this->value = $normalized;
}
}
public function __construct(string $value)
{
$this->value = $value;
}
}
Normalizacja zostaje przy polu. Caller pisze $email->value, a reguły domeny nie uciekają do serwisu aplikacyjnego.
Asymmetric visibility bez boileplate’u
Chcesz, żeby właściwość była publicznie czytelna, ale zapisywalna tylko w klasie? W 8.4 nie musisz pisać gettera tylko po to.
final class Order
{
public function __construct(
public private(set) string $id,
public private(set) string $status,
) {}
public function markPaid(): void
{
$this->status = 'paid';
}
}
Z zewnątrz czytasz $order->status. Zmiana statusu idzie przez metodę, która zna reguły przejść. Kod wygląda jak dane, a zachowanie zostaje domknięte.
Gdzie hooks pomagają, a gdzie przeszkadzają
Dobrze wchodzą w value objecty, DTO z lekką normalizacją i modele, w których getter nic nie robi poza zwrotem pola.
Gorzej, gdy:
- logika w
setwoła bazę albo HTTP (trudno testować, trudno czytać), - właściwość jest tablicą i spodziewasz się pełnej semantyki referencji,
- zespół jeszcze nie ma PHP 8.4 na wszystkich środowiskach, a polyfille i tak nie oddadzą składni języka.
Hook to nie miejsce na orchestration. To miejsce na niezmienniki i prostą transformację wartości.
Migracja bez big bang
Nie przepisuj całego modelu w weekend. Zacznij od nowych klas i od miejsc, gdzie getter/setter tylko szumią. W Symfony i Doctrine sprawdź, czy hydracja i proxy nie zakładają starego kształtu API. W serializacji (symfony/serializer, JMS) upewnij się, że public properties z hookami zachowują się tak, jak oczekujesz w testach.
W kolejnym value objectcie napisz mniej kodu i zostaw regułę bliżej danych. Reszta zwykle przychodzi sama.