Dynamic Properties in PHP 8.2

Dani 1 Tallied Votes 71 Views Share

In my increasingly futile attempt to remain using the now-defunct CodeIgniter 3 framework, I came across something that I figure might be worth sharing in case anyone else is maintaining older PHP codebases and suddenly things start breaking after a PHP upgrade.

With PHP 8.2, there’s a new warning that’s catching a lot of people off guard: dynamic properties are now deprecated. What that means is, you can no longer just assign a new property to an object without explicitly declaring it first in the class. If you do, PHP throws a warning like:

Creation of dynamic property SomeClass::$foo is deprecated

This happens when you do things like:

$user = new User();
$user->nickname = 'Dani';

If nickname wasn’t already declared in the User class, PHP used to just shrug and let it slide. Not anymore.

Obviously the best thing to do if you encounter this is declare properties ahead of time (obviously). However, if you prefer not to touch and sort through and refactor a lot of old, crusty code that was not written by you, there's an easy fix: Add #[\AllowDynamicProperties] to the top of the class, as so:

#[\AllowDynamicProperties]
class Images extends CI_Controller
{
    ...
}

It's a nice and easy MacGyver patch, until it stops working as well. (DaniWeb is currently on PHP 8.3.8 and it's still working.)

Hope this helps someone!

Dani 4,675 The Queen of DaniWeb Administrator Featured Poster Premium Member

Oh, and an important bit I forgot to mention: PHP's built-in stdClass has the #[AllowDynamicProperties] attribute already added. In fact, you can see in the PHP docs that the definition of the stdClass is "a generic empty class with dynamic properties." That means that you can always be safe doing things like:

$user = new stdClass();
$user->nickname = 'Dani';
jkon 689 Posting Whiz in Training Featured Poster

I can't get it , why anyone would want to
$user = new User(); $user->nickname = 'Dani';
if nickname is not a public property of User , or even worse
$user = new stdClass(); $user->nickname = 'Dani';
?
Why ?

Dani 4,675 The Queen of DaniWeb Administrator Featured Poster Premium Member

The first I agree would not make much sense to do because one would presume that the User class has its own set of getters and setters for a reason, and just creating random properties on a whim defeats the purpose of organizing and structuring your code by having the class in the first place. Nevertheless, I ran into this exact issue while trying to make the latest version of CodeIgniter 3 (which has now been deprecated in favor of CodeIgniter 4.x) compatible with PHP 8.2/8.3. As hinted above, the built-in Image_lib controller class that manipulates images does, indeed, create dynamic properties.

The second, which you say is worse, is something that I have been guilty of in the past when it comes to temporary variables that, for whatever reason, I want to be an object instead of an array. IMHO, there are two easy ways to create temporary objects:

// Create a PHP object and set 2 properties
$temp_obj = new StdClass();
$temp_obj->foo = 'bar';
$temp_obj->baz = 'bat';

// Create a PHP array with 2 elements
$temp_arr = array(
    'foo' => 'bar';
    'baz' => 'bat';
);

// Convert a PHP array to a PHP object
$temp_obj = json_decode(json_encode($temp_arr));

This obviously does not make sense to do if you want to create or work with a User object or something of that sort. However, if your code requires a quick way of creating and working with a simple object, either of these methods should suffice. Doing a cursory glance at some of my code, I've used this in places where an object is expected to be passed into a function call, so I needed a quick way of creating a generic object to pass into the function and not use again.

Dani 4,675 The Queen of DaniWeb Administrator Featured Poster Premium Member

This obviously does not make sense to do if you want to create or work with a User object or something of that sort.

I realize that in my previous post I incorrectly gave the example of $user = new stdClass(); $user->nickname = 'Dani';. My intention was not to say that it was good coding practice to represent a user of the app with an object of a generic type and dynamically start setting its properties. I meant to only illustrate that syntactically it was permitted. Perhaps incorrectly, I chose to demonstrate by continuing with the same user example that was used in the tutorial.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.