了解疙瘩php源代码

时间:2013-11-25 14:17:26

标签: php dependency-injection lambda pimple

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);
 }

此处,如果对象位于factories对象存储(SplObjectStorage类型)中,则返回id为$ id的类的新实例。然后在最后一次返回时,$this->values[$id]被设置为该对象的新实例,并返回该新实例。

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

这是我不理解的路线。对于相同的$ id,该行应如何为offsetGet的不同调用返回相同的实例。它不会每次都返回一个新实例吗? 请帮我。我尝试了很多,但我没有得到它。

1 个答案:

答案 0 :(得分:3)

我查看了疙瘩的源代码,发现一旦对象被实例化并保存在$this->values[$id]中,offsetGet的下一次调用将从第二个if条件返回。 即这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]每次返回相同的实例。