Skip to content
Muhammet Şafak
tr
Languages 4 min read

Typed Properties and Arrow Functions in PHP 7.4

PHP 7.4 was released in November 2019. Typed properties and arrow functions significantly strengthen the language's type system and syntax.


PHP 7.4 shipped as a stable release in November 2019. I had been eagerly waiting for this final major version in the 7.x series — specifically for two features: typed properties and arrow functions. I’ve been using both in real production code for the past few weeks, and I want to share my impressions.

Typed Properties: Type Declarations for Class Properties

Before PHP 7.4, there was no official, language-level way to declare the type of a class property. You could write @var string in a docblock, but that was purely for IDE hints and documentation — it had no runtime effect.

With PHP 7.4, we can now do this:

<?php

class User
{
    public int $id;
    public string $name;
    public string $email;
    public ?string $phone = null;
    public DateTimeImmutable $createdAt;
}

These type declarations are enforced at runtime. Try assigning $user->id = 'text' and you’ll get a TypeError. This is essentially an extension of the parameter and return type declarations introduced in PHP 7.0, now applied to class properties.

Nullable Types and Default Values

You can use nullable types like ?string. One important thing to know: a typed property can only hold null if it’s declared as nullable (?T) or assigned a default value. Otherwise, reading an uninitialized property throws an Error:

<?php

class Product
{
    public string $name; // reading before initialization: Error
    public ?string $description = null; // safe to read
    public float $price = 0.0;
}

$p = new Product();
// echo $p->name; // Fatal error: Typed property not initialized

$p->name = 'Pen';
echo $p->name; // "Pen"

I found this behavior a bit odd at first. But it’s actually a guarantee: when constructing an object, you learn at runtime — explicitly — which properties you need to initialize. Combined with the habit of constructor injection, you simply never run into this problem:

<?php

class User
{
    public function __construct(
        public int $id,
        public string $name,
        public string $email,
        public ?string $phone = null
    ) {}
}

Note that constructor promotion isn’t available yet in PHP 7.4 (that comes with PHP 8.0), but you can achieve the same guarantee by assigning properties explicitly in the constructor.

Perfect for Value Objects

Typed properties add the most value in value objects. For classes that represent things like a currency, an address, or a coordinate, having explicit property types catches misuse early:

<?php

class Money
{
    public int $amount;   // in minor units (e.g. cents)
    public string $currency;

    public function __construct(int $amount, string $currency)
    {
        $this->amount = $amount;
        $this->currency = $currency;
    }
}

Moving from Docblocks to Real Types

Writing @var docblocks was a habit before typed properties, but nothing stopped them from being entered incorrectly or from falling out of sync over time. I’ve seen more than once a case where the code said @var int but the property was holding a string. A language-level type declaration makes that inconsistency impossible; the docblock is now an enforced contract, not an arbitrary comment.

Arrow Functions

PHP’s closure syntax has always been a bit verbose:

<?php

$multiplier = 3;
$result = array_map(function ($n) use ($multiplier) {
    return $n * $multiplier;
}, [1, 2, 3, 4, 5]);

The use ($multiplier) clause is required to capture a variable from the outer scope — but it’s distracting. PHP 7.4’s arrow function syntax cleans this up:

<?php

$multiplier = 3;
$result = array_map(fn($n) => $n * $multiplier, [1, 2, 3, 4, 5]);

Functions written with the fn keyword capture the outer scope automatically — no use needed. You also don’t write return — the single expression is returned implicitly.

In complex transformation chains, this makes a real difference:

<?php

$activeUserNames = array_map(
    fn($user) => $user->name,
    array_filter($users, fn($user) => $user->active)
);

The Constraint: Single Expression Only

Arrow functions can only contain a single expression. When you need multiple lines, the classic function + use syntax is still the right tool. This limitation can be annoying — especially when you need a condition or an intermediate variable and can’t use an arrow function. But the constraint is intentional: the single-expression requirement keeps arrow functions genuinely short and focused. If you want to write a longer function, you have to do it deliberately with the old syntax — which is itself a kind of design decision.

Closing Out the 7.x Series

PHP 7.4 is the last major release in the 7.x family. Typed properties and arrow functions are meaningful additions that strengthen PHP’s type system and functional programming patterns. PHP 8.0 promises a much bigger leap — a JIT compiler, union types, match expressions. But we’ll cross that bridge when we come to it.

For now, 7.4 is a mature, genuinely useful release that I have no hesitation running in production.

Tags: #PHP
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind