When PHP 8.4 Says “Deprecated: Creation of Dynamic Property” — What It Means and How to Fix It

When PHP 8.4 Says “Deprecated: Creation of Dynamic Property” — What It Means and How to Fix It
Photo by JF Martin / Unsplash

Upgrading to PHP 8.4 brings a wave of performance improvements and cleaner language features. But along with that comes one of the most commonly encountered warnings developers now see:

Deprecated: Creation of dynamic property SomeClass::$propertyName is deprecated.

If you’re seeing messages like this across your project — especially after upgrading from PHP 7.x or early 8.x — you’re not alone. This change touches a lot of legacy code written before strict property declarations became the norm.

Let’s dive deep into what’s going on, why it matters, and how to fix it the right way.


🧠 What Are Dynamic Properties?

In older versions of PHP, you could freely add properties to any object, even if the class didn’t declare them:

class User {}

$user = new User();
$user->name = 'Sony';  // ✅ Worked fine before PHP 8.2

This is called a dynamic property — a property created at runtime that doesn’t exist in the class definition.

It was convenient for quick prototypes, but in large codebases, it often led to typos, hard-to-track bugs, and unexpected behavior.

PHP’s internal engine also had to handle these ad-hoc properties dynamically, which introduced performance overhead.


⚠️ What Changed in PHP 8.2 — and Why It Matters in PHP 8.4

Starting in PHP 8.2, dynamic property creation was marked deprecated.
By PHP 8.4, the deprecation warning is far more aggressive — it will show up anywhere you try to set a property that doesn’t exist.

So if you have legacy classes like this:

class dataUsers {
    public function __construct() {
        $this->queryData = []; // ⚠️ Deprecated in PHP 8.4
    }
}

You’ll now get:

Deprecated: Creation of dynamic property dataUsers::$queryData is deprecated

✅ The Proper Fix: Explicit Property Declaration

The modern PHP way is simple — declare all properties explicitly in your class.

Example:

class dataUsers {
    public array $queryData = [];

    public function __construct() {
        // no warnings
    }
}

This ensures:

  • Static analysis tools (like PHPStan or Psalm) can catch type issues.
  • Better IDE autocompletion and refactoring.
  • Faster runtime performance since properties are no longer dynamically bound.

If you’re unsure about the type, you can use mixed:

public mixed $queryData;

🩹 Temporary Workaround: Allow Dynamic Properties

If you’re maintaining a large legacy project and can’t refactor everything at once, PHP gives you a temporary escape hatch:

#[AllowDynamicProperties]
class dataUsers {
    // dynamic properties still allowed here
}

This attribute tells PHP:

“I understand what I’m doing — don’t throw a deprecation warning for this class.”

But this should be a short-term patch, not a permanent fix.
The PHP core team has hinted that dynamic property support will be completely removed in PHP 9.0.


🧰 Alternative Option: Use stdClass for Dynamic Data

If your class is really just a data bucket, consider using the built-in stdClass instead:

$user = new stdClass();
$user->queryData = [];
$user->name = 'Sony';

This approach is perfect for flexible objects that don’t require strict typing or methods.

However, avoid mixing stdClass and your domain models — it reduces clarity in large applications.


🔍 How to Find and Fix All Dynamic Properties in Your Project

To refactor confidently, you’ll want to locate all instances where dynamic properties are being used.

1. Use Grep (or Ripgrep)

In Linux/macOS terminal:

grep -r '\$this->' /path/to/your/project | grep -v 'public' | grep -v 'protected' | grep -v 'private'

This helps identify $this->something assignments that may not have been declared.

2. Use PHPStan or Psalm

Run:

vendor/bin/phpstan analyse src

These static analyzers can detect undeclared properties automatically.


🧩 Edge Cases to Watch Out For

Here are some subtle scenarios where the warning might appear even if you think you’re safe:

1. Trait Assignments

If a trait assigns $this->something but the property isn’t declared in the consuming class, PHP will warn you.
✅ Fix: Declare the property in the main class.

2. Anonymous Classes

Anonymous classes (like those created inline for callbacks or mocks) can still hit this issue:

$anon = new class {
    public function __construct() {
        $this->temp = 'hello'; // deprecated
    }
};

✅ Fix: Declare the property or use a #[AllowDynamicProperties] attribute.

3. Framework Magic

Frameworks that rely on magic getters/setters (like Laravel’s Eloquent models) already handle this via __get() and __set().
They typically use the #[AllowDynamicProperties] attribute internally — so you don’t need to worry unless it’s your own class.


🏗️ Best Practices Moving Forward

  • Always declare your properties explicitly.
  • Use typed properties (int, string, array, etc.) wherever possible.
  • Keep #[AllowDynamicProperties] only for legacy compatibility.
  • Run PHPStan or Psalm as part of your CI pipeline to catch issues early.
  • For data-only structures, prefer DTOs (Data Transfer Objects) over free-form classes.

💡 Pro Tip: Automate the Fix

If you have hundreds of classes, consider writing a simple script that:

  1. Scans all .php files.
  2. Detects $this-> assignments inside class bodies.
  3. Inserts a declared property automatically if missing.

There are already open-source tools like rectorphp/rector that can automate this refactor with predefined rules for PHP 8.2+ compatibility.


🚀 Finally

The deprecation of dynamic properties is not PHP being strict for no reason — it’s part of a bigger movement toward cleaner, safer, and faster code.

It pushes developers to write more predictable classes, improves static analysis, and reduces subtle runtime bugs.

So while the warning may feel annoying at first, treating it seriously now will save you from future pain — especially as PHP 9 approaches.

Declare your properties, type them properly, and your codebase will thank you later.

Support Us

Share to Friends