与次要版本一样,PHP 8.2增加了一些弃用。弃用通常是令人沮丧的根源,但重要的是要意识到它们实际上非常有帮助。我已经写过关于处理一般弃用的文章,所以如果你已经感到沮丧,也许最好先看看那个帖子。今天,我想关注一个特别是在 PHP 8.2 中的弃用:弃用的动态属性。
所以首先,什么是动态属性?好吧,它们是类定义中不存在的属性,但在运行时动态设置在这些类的对象上。
例如这个Post
类没有name
属性,但是我们在运行时设置它:
class Post
{
}
// …
$post = new Post();
$post->name = 'Name';
var_dump($post->name); // 'Name'
自 PHP 8.2 起,这些动态属性将被弃用:
// …
$post->name = 'Name';
您将看到此消息:Deprecated: Creation of dynamic property Post::$name is deprecated
。
#实施__get
并且__set
仍然有效!
此时您可能会惊慌失措,因为动态属性是 PHP 元编程的重要组成部分——许多框架都依赖它!
不用担心:这个新的弃用不会影响任何实现__get
and的类__set
。实现这些神奇功能的类将继续按预期工作:
class Post
{
private array $properties = [];
public function __set(string $name, mixed $value): void
{
$this->properties[$name] = $value;
}
// …
}
// …
$post->name = 'Name';
的对象也是如此stdClass
,它们将像以前一样支持动态属性:
$object = new stdClass();
$object->name = 'Name'; // Works fine in PHP 8.2
现在一些聪明的读者可能会想:如果stdClass
仍然允许动态属性,如果你从它扩展会发生什么?
实际上,可以扩展 fromstdClass
以防止显示弃用通知。但是,我想说这个解决方案远非理想:
// Don't do this
class Post extends stdClass
{
}
$post = new Post();
$post->name = 'Name'; // Works in PHP 8.2
#更好的选择
如果您真的想在不实现__get
and的情况下使用动态属性__set
,那么有比从 扩展更好的选择stdClass
。
PHP 核心团队提供了一个名为.的内置属性AllowDynamicProperties
。顾名思义,它允许类上的动态属性,而不必依赖粗略的扩展:
#[AllowDynamicProperties]
class Post
{
}
$post = new Post();
$post->name = 'Name'; // All fine
#结束的想法
PHP 曾经是一种非常动态的语言,但现在已经远离这种思维方式一段时间了。就我个人而言,我认为接受更严格的规则并尽可能依赖静态分析是一件好事,因为我发现它会导致编写更好的代码。
我可以想象依赖动态属性的开发人员对这种变化不太满意。如果您在该组中,您可能会发现仔细研究静态分析很有用。如果您想了解更多信息,可以查看我的 PHP 之路:静态分析系列!
如果您愿意花一些时间来搞清楚静态分析,我相当肯定你们中的大多数人永远都不想回到动态编程语言的混乱状态。对于 PHP,我们很幸运这两个选项都可用,并且您可以逐渐迁移到更严格的类型系统。
所以,是的:这种弃用可能有点痛苦,但我相信这样做是最好的语言。请记住,在 PHP 9.0 之前它不会是致命错误,因此有足够的时间来处理它。
via https://stitcher.io/blog/deprecated-dynamic-properties-in-php-82