PHP Warning Deprecated: Creation of dynamic property is deprecated
Deprecated: Creation of dynamic property ... is deprecated
我越来越多地看到这种情况,我不知道我需要做什么来停止这种警告。
这是我的class:
class database {
public $username = "root";
public $password = "pasword";
public $port = 3306;
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->{$key} = $value;
}
}
}
这就是我实例化它的方式。
$db = new database(array(
'database' => 'db_name',
'server' => 'database.internal',
));
这给了我两条信息。
Deprecated: Creation of dynamic property database::$database is deprecated
Deprecated: Creation of dynamic property database::$server is deprecated
if (!property_exists($this, $key)) { throw new Exception('Unknown property'); }
它不会修复你的代码,但它至少会给你一个钩子,让你在钉住你的其他违规行为的过程。
- Alex Howansky 2022-12-21
这个警告是在告诉你有一个你试图设置的属性没有列在类的顶部。
当你运行这个时:
class database {
public $username = "root";
public $password = "pasword";
public $port = 3306;
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->{$key} = $value;
}
}
}
$db = new database(array(
'database' => 'db_name',
'server' => 'database.internal',
));
它大致上相当于这样:
class database {
public $username = "root";
public $password = "pasword";
public $port = 3306;
}
$db = new database;
$db->database = 'db_name';
$db->server = 'database.internal';
警告是,在类的定义中没有一行说$db->database
或$db->server
的存在。
目前,它们将被动态地创建为非类型化的公共属性,但在将来,你需要明确地声明它们。
class database {
public $database;
public $server;
public $username = "root";
public $password = "pasword";
public $port = 3306;
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->{$key} = $value;
}
}
}
$db = new database(array(
'database' => 'db_name',
'server' => 'database.internal',
));
在一些罕见的情况下,你实际上想说"这个类的属性是我在运行时决定添加的任何东西";在这种情况下,你可以使用#[AllowDynamicProperties]
属性,像这样。
#[AllowDynamicProperties]
class objectWithWhateverPropertiesIWant {
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->{$key} = $value;
}
}
}
因此,警告来自于构造函数添加动态类属性。如果你不需要动态传入这些字段,而且真的,你似乎把简单的事情搞得太复杂了,那就这样试试吧。
class database {
public $username = "root";
public $password = "pasword";
public $port = 3306;
public $database = 'db_name';
public $server = 'database.internal';
}
$db = new database();
你需要动态参数,有什么原因吗?你也可以这样做。
class database {
public $username = "root";
public $password = "pasword";
public $port = 3306;
public $database;
public $server;
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->{$key} = $value;
}
}
}
如果你提前添加参数,它们就不是动态的,你只是给已经存在的东西赋了一个值。
现在应该可以工作了,不会有任何警告。
$db = new database(array(
'database' => 'db_name',
'server' => 'database.internal',
));
new database()
时,对代码完成有帮助吗?
- Nigel Ren 2022-12-21
你可以通过将成员变量存储在一个数组中来避免指定一个明确的成员变量列表,就像这样:
class database {
public $data;
public function __construct($params = array())
{
foreach ($params as $key => $value)
{
$this->data[$key] = $value;
}
}
}
然后,你可以用你想要的任何参数实例化一个database
对象。
$db = new database(array(
'database' => 'db_name',
'server' => 'database.internal',
'foo' => 'bar', // etc.
));
当然,你可能想记录下预期的参数是什么,但至少你能够传入任何你想要的东西,并且能够在将来使用它,而不需要改变类的定义。
你所看到的警告信息与使用PHP中的一个功能有关,这个功能叫做"动态属性"。动态属性允许你通过使用变量名来设置和获取对象属性,就像你在数据库类的__construct
方法中做的那样。
快捷的解决方法:
public function __construct(array $params)
{
$this->username = $params['username'] ?? null;
$this->password = $params['password'] ?? null;
$this->port = $params['port'] ?? null;
}
为了解决这个警告,你可以在你的代码中删除对动态属性的使用,并使用更现代的方式来设置对象属性。
class database
{
public function __construct(
public string $username,
public string $password,
public int $port,
) {}
}
$db = new database(
username: 'root',
password: 'password',
port: 3306,
);
另外,你也可以使用__set
和__get
魔法方法来设置和获取对象的属性,就像这样。
public function __set($key, $value)
{
$this->$key = $value;
}
public function __get($key)
{
return $this->$key;
}
这将允许你使用$object->property
符号来设置和获取对象的属性,而不会触发警告信息。
$id
,$propName='id'; $this->{$propName}=42;
就可以;如果在类的顶部未声明$id
,$this->id=42;
将发出警告。
- IMSoP 2022-12-21
$this->{$key} = $value
是不是触发通知的原因,写$this->database - $value
会触发完全相同的信息。
- IMSoP 2022-12-21
一个替代性的解决方案,它是针对这个例子的,因为参数是很容易识别的。数据库有共同的参数,可供参考。
使用PHP 8命名的参数和构造函数属性推广,可以在构造函数中指定所有可能的参数(这有点啰嗦,但对代码的完成很有帮助),然后在创建实例时,参数的名字是固定的...
class database
{
public function __construct(
private string $database = '',
private string $server = '',
private string $port = '',
private string $user = '',
private string $password = ''
) {
}
}
那么,就用
$db = new database(
database: 'db_name',
server: 'database.internal',
);
在class{的上方添加这个就可以解决这个问题了。
#[\AllowDynamicProperties]
简单地将这个:
class database {
替换为:
class database extends \stdClass {