I just stumbled upon a case where property hooks were the best solution: https://andreas.heigl.org/2025/11/27/property-hooks-for-the-win/

#php #propertyhooks #php84 #pdo

Property-Hooks for the win

Property-Hooks were one of the really hot topics of last years PHP8.4 release. And I do have very strong opinions on them. They were and probably still are extremely hyped for something that in my personal opinion should be a very niche thing. In new projects you shouldn’t really need them.

But just today I had one of those situations where they helped me combine legacy code with new functionality.

The starting position

I am working on a project where we are using PDO and especially PDO::FETCH_CLASS to create Objects from our database-content.

So the code looks something like this:

function getAllFoos() : array{ $stmt = $this->executePdoQuery(<<<SQL SELECT * FROM table SQL); $stmt->setFetchMode(PDO::FETCH_CLASS, Foo::class); return $stmt->fetchAll();}

Foo looks something like this:

final class Foo { public string a; public string b;}

And the database-table looks something like this:

CREATE TABLE foo ( a VARCHAR(20), b VARCHAR(20),)

Everything worked as expected and calling getAllFoos got me a list of Foo-objects.

So Far so good.

Now I wanted to add a new field to the Foo-object and that should contain an Enum. Easy peasy.

final class Foo { public string a; public string b; private Status $status;}enum Status: string { case Open = 'open'; case Closed = 'closed';}

Now I need to update the database

ALTER TABLE foo ADD COLUMN `status` VARCHAR(10) NOT NULL DEFAULT 'open';

That’s it!

When testing that though I found that it wasn’t because now everything blew up when calling getAllFoos ….

What happened?

Well, as expected the fetchAll tried to hydrate the values of the Foo object wth the values from the DB. But the DB contains a string whereas the Foo object expects the respective enum.

There is no out of the box solution to this. PDO has no idea how to convert this database-value into something the object understands (it could infer the expected enum-type from the type-hint but that can get out of hand rather quickly when it’s not an enum bot any other object that doesn’t have a ::from method or…)

Property Hooks to the rescue.

So I had to find my own way around this. And here property hooks are awesome when one has to adapt to legacy code.

So this is what my Foo class now looks like

final class Foo { public string a; public string b; private Status $status { set(string|Status $value) { if (is_string($value)) { $value = Status::from($value); } $this->status = $value; } }}

Works like a charm now!

#legacy #pdo #php #propertyHooks

@Crell is it an oversight that get_class_vars is unable to see the property hooks 🤔 I know I should be using Reflection but get_object_vars is able to see them. For reference https://3v4l.org/qdcah

#propertyhooks #detection #php

get_class_vars vs get_object_vars vs property hooks - created on 3v4l.org

View the output of this script on 3v4l.org: the online PHP shell with 250+ PHP versions

with #php 8.4, we get #propertyHooks
#awesome !!!

the real question is... will #rector be able to automate the refactoring ?

anyone got some info about that ?

#php84