ocramius/lazy-property

该软件包已被废弃,不再维护。没有建议的替代软件包。

一个提供对象属性惰性实例化逻辑的库

资助软件包维护!
Ocramius


README

这个小库旨在提供非常简单高效的惰性属性加载

Latest Stable Version Latest Unstable Version

废弃

从PHP 8.3开始,动态属性不再允许“默认情况下”使用(不再允许动态属性)。虽然仍然可以通过显式声明(使用#[\AllowDynamicProperties]属性)来拥有动态属性,但这个软件包的方法不再被认为是安全或长期高效的。

基于这一点,该软件包已被弃用并废弃:请使用传统的PHP array

安装

建议的安装方法是通过 composer

composer require ocramius/lazy-property

用例

在许多需要惰性初始化私有/受保护属性的情况下,许多人编写了如下所示的类

class SomeService
{
    protected $dependency;

    public function doWork()
    {
        $this->getDependency()->delegateWork();
    }

    protected function getDependency()
    {
        return $this->dependency ?: $this->dependency = get_dependency_somehow();
    }
}

这是有问题的,因为实现者和子类化 SomeService 的人最终会写出

class SomethingElse extends SomeService
{
    public function doOtherWork()
    {
        $this->dependency->doMoreWork();
    }
}

这只有在 SomeService#getDependency() 至少被调用一次的情况下才能工作(这在某些情况下可能是真实的),因此是bug/头痛/自杀等原因的源头。

为了避免这个问题,实现 SomeService 同时也公开其受保护 $dependency 属性的开发者可以使用 LazyProperty\LazyPropertiesTrait 来解决问题

#[\AllowDynamicProperties]
class SomeService
{
    use \LazyProperty\LazyPropertiesTrait;

    protected MyDependency $dependency;

    public function __construct()
    {
        $this->initLazyProperties(['dependency']);
    }

    public function doWork()
    {
        // look ma! no getter!
        $this->dependency->delegateWork();
    }

    protected function getDependency()
    {
        return $this->dependency ?: $this->dependency = get_dependency_somehow();
    }
}

这样,任何对 SomeService#$dependency 的访问都会在属性尚未初始化的情况下调用 SomeService#getDependency()

class SomethingElse extends SomeService
{
    public function doOtherWork()
    {
        // always works
        $this->dependency->doMoreWork();
    }
}

请注意,为了使属性惰性,必须有一个获取器。

性能说明

使用 LazyProperty\LazyPropertiesTrait 可以加速在私有/受保护范围内大量进行获取器调用的应用程序。调用 SomeService#initLazyProperties() 以及第一次属性访问时有一些轻微的开销,但应该可以忽略不计。