学习Slim Framework for PHP v3 (五)--route怎么被调用的?

  上一篇中分析了get()如何加入新的route的,这篇来分析route是如何被调用的。

  首先,route是在routers里保存,router有在container中存放。container提供了get()方法获取里面的元素,性质类似于Set()。这个性质见Slim\Container的get()和Pimple\Container的 offsetGet()方法。

/**Slim/Container:**/
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws ContainerValueNotFoundException No entry was found for this identifier.
* @throws ContainerException Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get($id)
{
if (!$this->offsetExists($id)) {
throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id));
}
return $this->offsetGet($id);
} /**Pimple/Container:**/
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);
} $raw = $this->values[$id];
$val = $this->values[$id] = $raw($this);
$this->raw[$id] = $raw; $this->frozen[$id] = true; return $val;
}

  在项目中还用到了Trait这个类,其实它就相当于公共函数,可以被加载到每个类中,作为那个类的成员函数或属性。但是也存在着一些覆盖、冲突、优先级的问题,详细可见PHP Manual文档。说这个原因在于这个思路很好,不用去非要继承(当然估计也不能抽象),使用就好了,每个类都能用。

  辣椒吧...

  这里有一个个人认为很炫的魔术方法__invoke()。当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。这个魔术方法很炫啊,以调用函数的方式调用一个对象。棒棒哒….

  这个解决了在middleware栈中调用对象顶端middleware的疑惑:
public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res)
{
if (is_null($this->stack)) {
$this->seedMiddlewareStack();
}
/** @var callable $start */
$start = $this->stack->top();
$this->middlewareLock = true;
$resp = $start($req, $res);
$this->middlewareLock = false;
return $resp;
}
$resp = $start($req, $res);就是相当于调用了$start对象自己的__invoke()对象了。
分析下来,整个route被调用的流程大体如下:
     App->run();
          |
     App->process()
          |
     App->callMiddlewareStack()
          |
     App->__invoke()
          |
     route->run()
          |
     route->finalize()
          \
     route->addMiddleware()
          \
     route->__invoke();
  个人认为比较重要点在于:无论是APP还是每个route都有自己的middlewareStack,自己的栈中栈顶是加入的Middleware栈底是自己($this),这个费了我很多时间。第三是一个PHP的知识点,魔术方法__invoke(),可以直接通过函数的方式调用对象,记住是对象哦即obj(arg01,arg02)这样的方式,这时__invoke()方法就被激活了。APP在__invoke()调用了route,route在__invoke中执行了闭包函数。

上一篇:fedora 使用trove的redstack 安装openstack环境


下一篇:openstack trove weekly meeting时间即将更改