编程语言
首页 > 编程语言> > 了解pimple php源代码

了解pimple php源代码

作者:互联网

Pimple是Silex框架中使用的php中的简单依赖项注入容器.我正在遍历源代码here.在文档中,函数offsetGet返回附加到依赖项容器的类的相同实例. offsetGet的相关代码为:

public function offsetGet($id)
{
    if (!isset($this->keys[$id])) {
        throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
    }

    if (
        isset($this->raw[$id])
        || !is_object($this->values[$id])
        || isset($this->protected[$this->values[$id]])
        || !method_exists($this->values[$id], '__invoke')
    ) {
        return $this->values[$id];
    }

    if (isset($this->factories[$this->values[$id]])) {
        return $this->values[$id]($this);
    }

    $this->frozen[$id] = true;
    $this->raw[$id] = $this->values[$id];

    return $this->values[$id] = $this->values[$id]($this);
 }

在这里,如果对象在工厂Object Store(SplObjectStorage类型)中,则它将返回ID为$id的类的新实例.然后在最后一次返回中再次将$this-> values [$id]设置为对象的新实例,并返回该新实例.

return $this-> values [$id] = $this-> values [$id]($this).

这是我不明白的线.对于同一$id,该行应如何针对offsetGet的不同调用返回相同的实例.每次都不会返回新实例吗?
请帮我.我尝试了很多,但我不明白.

解决方法:

我查看了pimple的源代码,发现一旦实例化对象并将其保存在$this-> values [$id]中,对offsetGet的下一次调用将从第二个if条件返回.
即如果条件如下:

if (
    isset($this->raw[$id])
    || !is_object($this->values[$id])
    || isset($this->protected[$this->values[$id]])
    || !method_exists($this->values[$id], '__invoke')
) {
    return $this->values[$id];
}

看一下单元测试,我发现没有魔术方法__invoke的对象可以共享.如果对象具有魔术方法__invoke(即该对象可以视为函数),则每次都会返回一个新实例.
因此,您可以看到上述if语句的第一个,第二个和第三个条件返回false.但是第四个条件返回true,因此$this-> values [$id]每次都返回相同的实例.

标签:dependency-injection,pimple,php,lambda
来源: https://codeday.me/bug/20191122/2059842.html