PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

PHP 7.4 in practice – typed properties pitfalls, hydration, PHP 8.0 preview

by Henryk Tews / Monday, 13 January 2020 / Published in PHP

PHP 7.4 was released in November 2019. After migrating several Magento 2 modules to the new version I have a clear picture. Typed properties genuinely affect the way you write classes – but they also have pitfalls worth knowing. I show what works great, what surprises you, and what migration looks like in practice.

Typed properties – pitfalls during migration

The most common mistake when migrating to typed properties is uninitialised properties. Before PHP 7.4 an uninitialised property returned null with a warning. Now it throws an Error:

<?php

class CustomerData
{
    // Old code - worked because PHP returned null
    /** @var string */
    private $firstName;

    // New code - Error if read before assignment
    private string $firstName;

    public function getFirstName(): string
    {
        return $this->firstName; // Error if constructor did not assign it
    }
}

Fix: always initialise in the constructor or use a default value:

<?php

class CustomerData
{
    private string $firstName;
    private string $lastName;
    private ?string $company   = null; // nullable with default null
    private float $creditLimit = 0.0;  // default value

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName  = $lastName;
    }
}

Typed properties and database hydration

A typical Magento 2 pattern is hydrating a model from a database row. With typed properties you must cast during hydration – the database returns strings:

<?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();

        // Database returns strings - explicit casting is required
        $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; }
}

Without explicit casting PHP throws a TypeError when assigning string “1” to an int property – even though the value looks like a number.

Constructor promotion – preview from PHP 8.0

<?php

// PHP 7.4 - repetition in three places
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 - single declaration in the constructor
class ApiClient
{
    public function __construct(
        private string $baseUrl,
        private int $timeout,
        private \Psr\Log\LoggerInterface $logger
    ) {}
}

Arrow functions in everyday use

<?php

declare(strict_types=1);

// Transform product collection
$skus = array_map(
    fn(\Magento\Catalog\Api\Data\ProductInterface $p): string => $p->getSku(),
    $products
);

// Filter with access to outer variable - no use required
$minPrice   = 10.0;
$affordable = array_filter(
    $products,
    fn(\Magento\Catalog\Api\Data\ProductInterface $p): bool => $p->getPrice() >= $minPrice
);

// Multi-level sort
usort(
    $products,
    fn($a, $b) => [$a->getPrice(), $a->getSku()] <=> [$b->getPrice(), $b->getSku()]
);

Summary

PHP 7.4 after a few weeks in production projects works very well. Typed properties require discipline when hydrating from external data sources, but give instant type error detection. Arrow functions naturally replace closures with use everywhere you transform collections. Worth upgrading projects before PHP 8.0 – the changes are evolutionary and the migration is predictable.

About Henryk Tews

What you can read next

PHP 7.2 – object type hint, sodium instead of mcrypt, deprecations

© 2026 Created by

TOP
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 Always active
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.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Zobacz preferencje
  • {title}
  • {title}
  • {title}