"Creation of dynamic property is deprecated" in WordPress: what it means and how to fix it
The notice "Deprecated: Creation of dynamic property ... is deprecated" means some PHP code on your site is creating a dynamic property: it writes a value to a property the class never declared. PHP 8.2 deprecated this. The PHP RFC for this change says it becomes an Error exception in PHP 9.0. The real fix belongs in the code that triggers the notice. Declare the property in the class, which is the fix PHP's manual prefers, or add the #[\AllowDynamicProperties] attribute as an explicit opt-in. If the notice comes from a plugin or theme you don't maintain, update it or report it to its author. Until then, log the notice on a staging copy and keep it off the screen on your live site.
What the notice is telling you
PHP's migration notes for PHP 8.2 put it plainly: the creation of dynamic properties is deprecated, unless the class opts in by using the #[\AllowDynamicProperties] attribute. A "dynamic property" is one the code creates by assigning to it, such as $this->settings = ..., when the class has no declared $settings property.
The message names the class and the property that caused it, in this form:
Deprecated: Creation of dynamic property Foo::$bar is deprecatedHere Foo is the class and $bar is the undeclared property. PHP's manual example also shows the notice ending with the file and line. That is your best clue to which plugin or theme is responsible.
Some code is not affected. stdClass allows dynamic properties, and PHP's notes say that using the __get() and __set() magic methods is not affected by this change. The RFC also shows that a later assignment to the same property gives no deprecation warning, because the dynamic property already exists.
PHP describes E_DEPRECATED as warnings about code that will not work in future versions. Treat it as advance notice. Because the RFC says this becomes an Error exception in PHP 9.0, a notice you ignore now can become an error after that upgrade.
Find which plugin or theme raises it
If the notice appears on your pages, copy the whole line, including the file path and line number. Read the path to see which plugin or theme folder the file is in. If you want a full list, turn on WordPress's debug log on a staging copy of the site and load the pages that show the notice.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );- WP_DEBUG_LOG is a companion to WP_DEBUG that causes all errors to also be saved to a debug.log file. The log is saved to debug.log in the content directory, usually wp-content/debug.log.
- WP_DEBUG_LOG does nothing unless WP_DEBUG is enabled (true).
- By default, WP_DEBUG_DISPLAY shows errors and warnings as they are generated. Setting it to false will hide all errors.
- The WordPress handbook does not recommend using WP_DEBUG or the other debug tools on live sites. Do this on a local or staging copy.
Once you have the log, search it for "Creation of dynamic property". Group the lines by file path. Each group is one plugin or theme to deal with. Several lines from the same class can be handled with one fix that declares all of its properties.
Fix it in code you own
If the class is in your own plugin, theme or child theme, you can fix it yourself. PHP's manual marks declaring the property as the preferred fix.
Declare the property. Add it to the class body, so the assignment writes to a declared property instead of creating one:
class My_Plugin_Widget {
public function __construct() {
$this->settings = get_option( 'my_widget_settings' );
}
}class My_Plugin_Widget {
public $settings;
public function __construct() {
$this->settings = get_option( 'my_widget_settings' );
}
}Mark the class with the attribute. PHP's manual says #[\AllowDynamicProperties] was introduced in PHP 8.2.0 as the explicit way to allow dynamic properties. Its effect is inherited: child classes of a class marked with this attribute also allow dynamic properties. That makes it a quick opt-in for a large legacy class. Declaring properties is still the cleaner long-term fix, because each one you declare is one fewer thing that can surprise you.
#[\AllowDynamicProperties]
class My_Legacy_Widget {
// existing code unchanged
}Use a WeakMap for objects you don't own. Sometimes your code attaches extra data to an object from WordPress core or another plugin. PHP's manual suggests a WeakMap when additional data needs to be associated with an object which one does not own, and the RFC calls this a way to store the information in a non-intrusive way. Keep the data in your own map, keyed by the object, instead of setting a new property on it.
Classes that already route property access through __get() and __set() are not affected, so you don't need to change those for this notice.
When the notice comes from someone else's plugin or theme
If the notice comes from code you didn't write, the fix belongs to its author. Your job is to get it to them and keep your site tidy in the meantime.
- Update first. Check for a newer version of the plugin or theme and read its changelog for PHP compatibility fixes. Apply the update on staging, then check the log again.
- Search the plugin's support forum or issue tracker for the class and property named in the notice before you open a new report.
- If nobody has reported it, include the full notice line, your PHP version and the plugin version. The notice names the class, the property, the file and the line, which is what the author needs to find it.
- Avoid editing the plugin's or theme's files yourself. If you must patch something urgently, keep a note of the change so you can check it after every update.
- On the live site, keep WP_DEBUG_DISPLAY off so visitors never see the notices, and keep the debugging itself on staging.
Check the rest of your site before the next PHP upgrade
If one plugin raises this notice, it is worth checking the other plugins and themes before your host moves you to a newer PHP version. Test the upgrade on a staging copy, read the debug log there, and fix or replace what fails before you switch the live site.
If you use a scanner for that check, treat a clean result as a good sign, not a guarantee, and still test on staging.
Whatever tool you use, the order is the same. Find the file and line, fix code you own by declaring the property, and send the rest to the people who maintain it.
Sources
- PHP manual: Deprecated features in PHP 8.2
- PHP RFC: Deprecate dynamic properties
- PHP manual: the AllowDynamicProperties attribute
- PHP manual: predefined error constants (E_DEPRECATED)
- WordPress Advanced Administration Handbook: Debugging in WordPress
Questions
Will my WordPress site break because of this notice?
It is a deprecation notice, which PHP describes as a warning about code that will not work in future versions. The PHP RFC says creating a dynamic property becomes an Error exception in PHP 9.0, so get the code fixed before you move to that version.
Is adding #[\AllowDynamicProperties] a proper fix?
It is the explicit way PHP 8.2.0 introduced to allow dynamic properties, and it also applies to all child classes. PHP's manual lists declaring the property as the preferred fix, so use the attribute as a stopgap for large legacy classes and declare properties where you can.
Why do visitors see the notice on my pages?
By default, WP_DEBUG_DISPLAY shows errors and warnings as they are generated. Setting it to false will hide all errors. Pair it with WP_DEBUG_LOG on a staging copy so you can still read them in the debug.log file in the content directory, usually wp-content/debug.log.
Does code that uses stdClass or __get()/__set() trigger it?
No. stdClass allows dynamic properties, and PHP's notes say that using the __get() and __set() magic methods is not affected by this change.