提问人:Johnny 3653925 提问时间:12/22/2022 最后编辑:ADysonJohnny 3653925 更新时间:11/3/2023 访问量:72994
PHP 警告已弃用:不推荐创建动态属性
PHP Warning Deprecated: Creation of dynamic property is deprecated
问:
我越来越多地看到这种情况,我不确定我需要做些什么来阻止此警告:
已弃用:创建动态属性...已弃用
这是我的班级:
class database {
public $username = "root";
public $password = "password";
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',
));
这给了我两条信息:
已弃用:创建动态属性数据库::$database 荒废的
已弃用:创建动态属性 database::$server 是 荒废的
答:
因此,警告来自添加动态类属性的构造函数。如果你不必动态地、真正地传入这些字段,那么你似乎确实把一些简单的事情复杂化了,那么试试这样吧。
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()
另一种解决方案,特定于此示例,因为参数非常容易识别。数据库具有引用的公共参数。
使用 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',
);
评论
您看到的警告消息与使用 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,
);
或者,也可以使用 和 magic 方法来设置和获取对象属性,如下所示:__set
__get
public function __set($key, $value)
{
$this->$key = $value;
}
public function __get($key)
{
return $this->$key;
}
这将允许您使用表示法来设置和获取对象属性,而不会触发警告消息。$object->property
评论
$propName='id'; $this->{$propName}=42;
$id
$this->id=42;
$id
$this->{$key} = $value
$this->database - $value
通过将成员变量存储在单个数组中,可以避免指定成员变量的显式列表,如下所示:
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.
));
当然,您可能希望记录预期的参数是什么,但至少您可以传入任何您想要的内容,并且能够在将来使用它,而无需更改类定义。
评论
该警告告诉您,您正在尝试设置一个属性,该属性未在类或其任何父类中声明。
运行此命令时:
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';
警告是,类定义中没有一行表明 or 存在。$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;
}
}
}
评论
use AllowDynamicProperties;
在类上方添加 AllowDynamicProperties 将使警告消失:
#[\AllowDynamicProperties]
class database {
评论
$this->databsae = new DB;
$this->database = new DB;
private
protected
如果您只想不显示警告,只需替换以下命令:
class database {
为此:
class database extends \stdClass {
评论
if (!property_exists($this, $key)) { throw new Exception('Unknown property'); }