PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

PHP 7.4 w praktyce – pułapki typed properties, hydratacja, zapowiedź PHP 8.0

by Henryk Tews / poniedziałek, 13 stycznia 2020 / Opublikowano w PHP

PHP 7.4 wyszło w listopadzie 2019. Miałem kilka tygodni na przejście kilku modułów Magento 2 na nową wersję i wyrobienie sobie zdania. Typed properties to zmiana, która realnie wpływa na sposób pisania klas – ale ma też kilka pułapek, na które warto uważać. Pokazuję co działa świetnie, co zaskakuje i jak wygląda migracja istniejącego kodu.

Typed properties – pułapki przy migracji

Najpopularniejszy błąd przy migracji na typed properties to niezainicjalizowane właściwości. Przed PHP 7.4 niezainicjalizowana właściwość zwracała null z ostrzeżeniem. Teraz rzuca Error:

<?php

declare(strict_types=1);

class CustomerData
{
    // Stary kod - działało, bo PHP zwracało null
    /** @var string */
    private $firstName;

    // Nowy kod - Error jeśli odczytasz przed przypisaniem
    private string $firstName;

    public function getFirstName(): string
    {
        // Jeśli konstruktor nie przypisał $firstName - Error tutaj
        return $this->firstName;
    }
}

Rozwiązanie – zawsze inicjalizuj w konstruktorze lub użyj wartości domyślnej:

<?php

declare(strict_types=1);

class CustomerData
{
    private string $firstName;
    private string $lastName;
    private ?string $company = null; // nullable z domyślnym null
    private float $creditLimit = 0.0; // wartość domyślna

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName  = $lastName;
        // $company i $creditLimit mają wartości domyślne - ok
    }
}

Typed properties a serializacja i hydratacja

Typowy wzorzec w Magento 2 to hydratacja modelu z tablicy danych z bazy. Z typed properties musisz uważać na typy podczas hydratacji:

<?php

declare(strict_types=1);

class ProductData
{
    private int $id;
    private string $sku;
    private float $price;
    private bool $isActive;

    public static function fromArray(array $data): self
    {
        $obj = new self();

        // Baza danych zwraca stringi - rzutowanie konieczne
        $obj->id       = (int) $data['entity_id'];
        $obj->sku      = (string) $data['sku'];
        $obj->price    = (float) $data['price'];
        $obj->isActive = (bool) $data['status'];

        return $obj;
    }

    public function getId(): int     { return $this->id; }
    public function getSku(): string { return $this->sku; }
    public function getPrice(): float { return $this->price; }
    public function isActive(): bool  { return $this->isActive; }
}

Bez jawnego rzutowania PHP rzuci TypeError przy próbie przypisania stringa „1” do właściwości int – nawet jeśli wartość wygląda jak liczba.

Constructor promotion – zapowiedź z PHP 8.0

PHP 8.0 zapowiada Constructor Property Promotion – skrócony zapis, który eliminuje powtarzanie właściwości w deklaracji i konstruktorze. To naturalne rozwinięcie typed properties:

<?php

// PHP 7.4 - powtarzanie w trzech miejscach
class ApiClient
{
    private string $baseUrl;
    private int $timeout;
    private \Psr\Log\LoggerInterface $logger;

    public function __construct(
        string $baseUrl,
        int $timeout,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->baseUrl = $baseUrl;
        $this->timeout = $timeout;
        $this->logger  = $logger;
    }
}

// PHP 8.0 - jeden zapis w konstruktorze
class ApiClient
{
    public function __construct(
        private string $baseUrl,
        private int $timeout,
        private \Psr\Log\LoggerInterface $logger
    ) {}
}

PHP 8.0 przyniesie też union types, match expression i named arguments. Więcej o tym gdy wyjdzie.

Arrow functions w codziennym użyciu – po kilku tygodniach

Arrow functions (PHP 7.4) bardzo naturalnie weszły do kodu przy operacjach na kolekcjach. Kilka wzorców, których używam najczęściej:

<?php

declare(strict_types=1);

// Transformacja kolekcji produktów
$skus = array_map(
    fn(\Magento\Catalog\Api\Data\ProductInterface $p): string => $p->getSku(),
    $products
);

// Filtrowanie z dostępem do zewnętrznej zmiennej - bez use
$minPrice = 10.0;
$affordable = array_filter(
    $products,
    fn(\Magento\Catalog\Api\Data\ProductInterface $p): bool => $p->getPrice() >= $minPrice
);

// Sortowanie wielopoziomowe
usort(
    $products,
    fn($a, $b) => [$a->getPrice(), $a->getSku()] <=> [$b->getPrice(), $b->getSku()]
);

// Zagnieżdżone arrow functions - $factor przechwycony z zewnątrz
$factor = 1.23;
$withTax = array_map(
    fn(float $price): float => round($price * $factor, 2),
    $prices
);

Null coalescing assignment w praktyce

Operator ??= z PHP 7.4 pojawia się naturalnie przy lazy initialization i przy pracy z konfiguracją:

<?php

declare(strict_types=1);

class ConfigProvider
{
    private array $cache = [];

    public function get(string $path, mixed $default = null): mixed
    {
        // Zamiast: $this->cache[$path] = $this->cache[$path] ?? $this->load($path);
        $this->cache[$path] ??= $this->load($path) ?? $default;
        return $this->cache[$path];
    }

    private function load(string $path): mixed
    {
        // ładowanie z bazy lub pliku
        return null;
    }
}

// Przy budowaniu tablic z opcjonalnymi kluczami
$options = [];
$options['timeout']  ??= 30;
$options['retries']  ??= 3;
$options['debug']    ??= false;

Podsumowanie

PHP 7.4 po kilku tygodniach w produkcyjnych projektach sprawdza się bardzo dobrze. Typed properties wymagają dyscypliny przy hydratacji danych z zewnętrznych źródeł, ale w zamian dają natychmiastowe wykrywanie błędów typów. Arrow functions naturalnie zastępują closures z use wszędzie tam gdzie transformujesz kolekcje. Warto zaktualizować projekty zanim pojawi się PHP 8.0 – zmiany są ewolucyjne i migracja jest przewidywalna.

About Henryk Tews

Co możesz przeczytać następne

Typowanie w PHP 7.x, strict_types, PHPStan, przygotowanie na PHP 7.4
Zasady SOLID w PHP – teoria przekuta w kod
Magento 2.4.9 – oficjalne wsparcie PHP 8.5, co się zmieniło i jak migrować
  • 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}