PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

PHP 8.4 – property hooks, asymetryczna widoczność i nowe funkcje tablic

by Henryk Tews / środa, 30 września 2026 / Opublikowano w PHP

PHP 8.4 jest dostępny od listopada 2024. Przynosi property hooks – natywną implementację getterów i setterów bez boilerplate, asymetryczną widoczność właściwości (public private(set)), nowe funkcje tablic i deprecację funkcji które nie były dotykane od PHP 4. To ewolucja która pozwala pisać bardziej zwięzły kod bez rezygnacji z enkapsulacji.

Property hooks – natywne gettery i settery

<?php

declare(strict_types=1);

// PHP 8.3: klasa z boilerplate getterów/setterów
class OrderItem83
{
    private float $price;
    private int   $qty;

    public function getPrice(): float { return $this->price; }
    public function setPrice(float $price): void
    {
        if ($price < 0) throw new \InvalidArgumentException('Price cannot be negative');
        $this->price = $price;
    }

    public function getQty(): int { return $this->qty; }
    public function setQty(int $qty): void
    {
        if ($qty < 1) throw new \InvalidArgumentException('Qty must be positive');
        $this->qty = $qty;
    }

    public function getTotal(): float { return $this->price * $this->qty; }
}

// PHP 8.4: property hooks - logika bezpośrednio przy właściwości
class OrderItem84
{
    public float $price {
        set(float $value) {
            if ($value < 0) throw new \InvalidArgumentException('Price cannot be negative');
            $this->price = $value;
        }
        get => $this->price;
    }

    public int $qty {
        set(int $value) {
            if ($value < 1) throw new \InvalidArgumentException('Qty must be positive');
            $this->qty = $value;
        }
    }

    // Hook tylko get - wirtualna właściwość obliczana
    public float $total {
        get => $this->price * $this->qty;
    }
}

$item = new OrderItem84();
$item->price = 99.99;  // wywołuje set hook
$item->qty   = 3;
echo $item->total;     // wywołuje get hook: 299.97
// $item->total = 100; // Fatal error: właściwość z samym get jest readonly

Asymetryczna widoczność właściwości

<?php

declare(strict_types=1);

// PHP 8.4: public właściwość którą tylko klasa może modyfikować
class Product
{
    public private(set) string $sku;
    public private(set) float  $price;
    public protected(set) int  $stock;  // tylko klasa i dzieci mogą ustawiać

    public function __construct(string $sku, float $price, int $stock)
    {
        $this->sku   = $sku;
        $this->price = $price;
        $this->stock = $stock;
    }

    public function applyDiscount(float $percent): void
    {
        $this->price = $this->price * (1 - $percent / 100); // OK - wewnątrz klasy
    }

    public function reserveStock(int $qty): void
    {
        if ($qty > $this->stock) throw new \RuntimeException('Not enough stock');
        $this->stock -= $qty;
    }
}

$product = new Product('SKU-001', 100.0, 50);

echo $product->sku;    // OK - public read
echo $product->price;  // OK - public read
echo $product->stock;  // OK - public read

$product->price = 50;  // Fatal error: Cannot modify private(set) property
// $product->sku = 'X'; // Fatal error

$product->applyDiscount(10); // OK - wewnątrz klasy
echo $product->price;  // 90.0

Nowe funkcje tablic – array_find() i spółka

<?php

declare(strict_types=1);

$orders = [
    ['id' => 1, 'status' => 'complete',   'total' => 150.0],
    ['id' => 2, 'status' => 'pending',    'total' => 89.99],
    ['id' => 3, 'status' => 'processing', 'total' => 230.0],
    ['id' => 4, 'status' => 'pending',    'total' => 45.0],
];

// PHP 8.4: array_find() - pierwszy element spełniający warunek
$firstPending = array_find($orders, fn($o) => $o['status'] === 'pending');
// ['id' => 2, 'status' => 'pending', 'total' => 89.99]

// PHP 8.4: array_find_key() - klucz pierwszego pasującego elementu
$key = array_find_key($orders, fn($o) => $o['total'] > 200);
// 2 (indeks zamówienia z total 230)

// PHP 8.4: array_any() - czy jakikolwiek element spełnia warunek
$hasPending = array_any($orders, fn($o) => $o['status'] === 'pending');
// true

// PHP 8.4: array_all() - czy wszystkie elementy spełniają warunek
$allComplete = array_all($orders, fn($o) => $o['status'] === 'complete');
// false

// Przed PHP 8.4 wymagało array_filter + count lub foreach z break

Deprecacje i zmiany breaking

<?php

// PHP 8.4 deprecuje implicit nullable - musisz być jawny
// PHP 8.3 (działało bez ostrzeżenia):
function oldStyle(string $name = null): void {}

// PHP 8.4 (deprecated - rzuca E_DEPRECATED):
// function oldStyle(string $name = null): void {}

// PHP 8.4 (poprawnie):
function newStyle(?string $name = null): void {}
// lub:
function newStyle2(string|null $name = null): void {}

// Dotyczy wszystkich type hints - warto przejść kod przez:
// vendor/bin/phpstan analyse --level=6 app/code/
// lub rector:
// vendor/bin/rector process app/code/ --config rector.php

Podsumowanie

PHP 8.4 property hooks eliminują potrzebę pisania getterów i setterów przy zachowaniu pełnej enkapsulacji. Asymetryczna widoczność (public private(set)) pozwala mieć właściwości które są publiczne do odczytu ale prywatne do zapisu – bez dodatkowego kodu. Nowe funkcje tablic wypełniają lukę którą dotychczas zamykał się przez array_filter i foreach. Przed aktualizacją sprawdź implicit nullable – to najczęstszy problem przy migracji.

About Henryk Tews

Co możesz przeczytać następne

PimCore – CMS + PIM + DAM, klasy obiektów, Data Hub GraphQL, integracja z Magento
PHP 8.3 po premierze – typed constants, json_validate(), clone with w praktyce
Typowanie w PHP 7.x, strict_types, PHPStan, przygotowanie na PHP 7.4
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}