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
的不同调用返回相同的实例。它不会每次都返回一个新实例吗?
请帮我。我尝试了很多,但我没有得到它。
答案 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]
每次返回相同的实例。