Skip to content

PHP Dynamic Property Deprecation Warning

PHP 8.2 introduced a significant change that impacts dynamic property creation in classes. This article explains why you encounter the Deprecated: Creation of dynamic property is deprecated warning and how to resolve it correctly.

Problem Statement

In PHP versions before 8.2, you could add new properties to an object dynamically without declaring them in the class definition. This behavior is now deprecated and triggers a warning:

php
class Database {
    public $username = "root";
    public $password = "password";
    public $port = 3306;

    public function __construct($params = []) {
        foreach ($params as $key => $value) {
            $this->{$key} = $value;  // Triggers warning if property doesn't exist
        }
    }
}

// Usage:
$db = new Database([
    'database' => 'db_name',   // Undeclared property
    'server' => 'database.internal'  // Undeclared property
]);

// Outputs:
// Deprecated: Creation of dynamic property Database::$database is deprecated
// Deprecated: Creation of dynamic property Database::$server is deprecated

Key Reasons for Deprecation:

  • Prevents typos in property names that create hard-to-debug issues
  • Improves performance by enabling more efficient class structure compilation
  • Encourages explicit class design and better documentation

1. Declare Properties Explicitly (Best Practice)

Declare all properties directly in your class to satisfy PHP's strict property requirements.

php
class Database {
    public $username = "root";
    public $password = "password";
    public $port = 3306;
    public string $database = '';
    public string $server = '';

    public function __construct(array $params = []) {
        foreach ($params as $key => $value) {
            if (property_exists($this, $key)) {
                $this->{$key} = $value;
            }
        }
    }
}

Advantages:

  • Clear definition of class capabilities
  • Prevents dynamic property misuse
  • Enables type safety (PHP 7.4+ typed properties)

2. Use Constructor Property Promotion (PHP 8.0+)

Leverage modern PHP syntax to declare and initialize properties in the constructor.

php
class Database {
    public function __construct(
        public string $database = '',
        public string $server = '',
        public string $username = "root",
        public string $password = "password",
        public int $port = 3306
    ) {
        // No loop needed
    }
}

// Usage:
$db = new Database(
    database: 'db_name',
    server: 'database.internal'
);

3. Container Pattern for Dynamic Data

If you truly need dynamic data storage, use a dedicated array property.

php
class Database {
    public array $config = [];
    
    public function __construct(array $params = []) {
        $this->config = $params;
    }
}

// Access data via:
$db->config['database']; // Instead of $db->database

Less Ideal Workarounds

Not Recommended for New Code

These solutions suppress warnings but don't fix the structural issues:

php
// 1. Allow dynamic properties (not future-proof)
#[\AllowDynamicProperties]
class Database {
    ...
}

// 2. Extend stdClass (hides warning, inherits magic behavior)
class Database extends \stdClass {
    ...
}

Important Considerations

  1. Legacy Code Migration:
    For older codebases, use property_exists() checks during refactoring:

    php
    public function __construct(array $params = []) {
        foreach ($params as $key => $value) {
            if (property_exists($this, $key)) {
                $this->{$key} = $value;
            }
            // Silently ignores invalid properties
        }
    }
  2. Backward Compatibility:
    PHP 8.2 only emits warnings – the functionality remains until PHP 9.0, but prepare code now.

  3. Dynamic Properties Use Case:
    Valid cases for #[\AllowDynamicProperties] are rare (typically internal framework classes). For userland code, explicit declaration is preferred.

Conclusion

PHP 8.2's dynamic property deprecation encourages better class design practices:

  1. Always declare properties explicitly with appropriate visibility and types
  2. Use constructor property promotion for concise syntax (PHP 8.0+)
  3. Avoid dynamic property assignment in new code
  4. Refactor legacy code using existence checks during migration

By following these practices, your code remains compatible with future PHP versions while improving maintainability and reducing runtime errors.