3

Pimple 是一个简单的 php 依赖注入容器,用于 silex 框架。我在这里浏览了源代码。在文档中,该函数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);
 }

在这里,如果对象在factoriesObject Store( SplObjectStoragetype) 中,它会返回一个新的类实例,id 为 $id。然后在最后一次返回中再次$this->values[$id]设置为对象的新实例并返回该新实例。

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

这是我无法理解的线。这条线应该如何为offsetGet相同的 $id 的不同调用返回相同的实例。它不会每次都返回一个新实例吗?请帮我。我尝试了很多,但我不明白。

4

1 回答 1

3

我查看了 pimple 的源代码,发现一旦对象被实例化并保存在 中$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]每次都返回相同的实例。

于 2013-12-11T09:35:14.643 回答