【问题标题】:Zend View behaviour in a Swoole http serverSwoole http 服务器中的 Zend View 行为
【发布时间】:2018-09-21 10:20:33
【问题描述】:

我们正面临一个使用 Zend View 并在 swoole http 服务器中运行的 Zend Expressive 应用程序的奇怪行为。这种行为与单例模式有关。

我们已将 Zend Expressive 配置为在 swoole http 服务器 - https://docs.zendframework.com/zend-expressive-swoole/ 中运行 - 并且所有 api 编程工作都没有问题(swoole 是火箭!)

但是我们已经尝试进入下一步,我们已经尝试通过 swoole http 服务器执行一个 web 界面。

在那里,我们发现了奇怪的行为。为了简化我的问题(我们使用了很多视图助手),我们的 Web 界面与 Zend View 一起使用并使用了 headTitle 助手。当您第一次加载 Web 界面时一切正常,但当您重新加载页面时,您会看到元标题重复。

我们的处理程序是下一个

public function handle(ServerRequestInterface $request) : ResponseInterface
{
    $data = [
        "rand" => rand(1000, 9999),
        "time" => date("Y-m-d H:i:s")
    ];
    return new HtmlResponse($this->template->render('app::my-view', $data));
}

接下来是我们的观点

<?php $this->headTitle('My Page'); ?>
<b>Rand</b>: <?php echo $rand; ?><br>
<b>Time</b>: <?php echo $time; ?><br>
<hr>

在 Google 中搜索我们发现 https://framework.zend.com/blog/2018-03-21-expressive-swoole.html Zend 的团队遇到了类似的问题:

但是,对于异步服务器,每个服务器都将使用相同的实例 和每一个请求。通常,对 PSR-7 消息实例的操作 将创建新实例,因为它们实现的接口是 指定为不可变。不幸的是,由于技术限制 PHP 语言,我们无法制作响应消息的正文 不可变的。这意味着如果一个进程写入该主体,那么一个 后续流程——甚至是并行执行的流程! - 将要 收到相同的更改。这可能导致,在最好的情况下, 重复的内容,并且在最坏的情况下提供不正确的内容或 进行信息泄露!

他们已经解决了这个问题

为了应对这些情况,我们修改了 我们注册的 Psr\Http\Message\ResponseInterface 服务 依赖注入容器:它现在不返回 接口,而是一个能够产生实例的工厂

但是检查 Zend Framework 类,我们发现我们遇到了另一个问题,因为解决方案是在代码中实现的,并且对 api 的所有请求都是正确的

在zend-expressive-swoole/src/ConfigProvider.php中可以看到

ServerRequestInterface::class         => ServerRequestSwooleFactory::class,

然后我们改变观点并检查 zend 视图助手,我们发现视图助手 HeadTitle 扩展自 Container\AbstractStandalone

file: zend-view/src/Helper/HeadTitle
class HeadTitle extends Placeholder\Container\AbstractStandalone

查看这个 AbstractStandalone,我们发现在构造函数方法中,容器是通过单例加载的

file: zend-view/src/Helper/Placeholder\Container\AbstractStandalone
public function getContainer()
{
    if (! $this->container instanceof AbstractContainer) {
        $this->container = new $this->containerClass();
    }
    return $this->container;
}

这就是问题所在。使用 Zend Expressive Swoole 模块,每个请求和每个响应都是独立的,但会反复使用同一个 Singleton 容器。

你遇到过这个问题吗?你是怎么解决这个问题的?

我们正在考虑创建一个自定义助手来删除所有视图助手容器,但如果这样做,我们必须更改大量视图文件以添加这个新的自定义助手。

提前致谢

【问题讨论】:

    标签: zend-framework singleton zend-view mezzio swoole


    【解决方案1】:

    我在https://github.com/zendframework/zend-expressive-swoole/issues/34 向 zend-expressive-swoole 库开发团队提出了这个问题,他们向我展示了一种方法:

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $layout  = clone $this->layout;
        $this->phpRenderer->viewModel()->setRoot($layout);
        $this->phpRenderer->headTitle()->deleteContainer();
        $this->phpRenderer->headMeta()->deleteContainer();
        $this->phpRenderer->seo()->reset();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 2011-07-24
      • 1970-01-01
      • 2014-09-22
      相关资源
      最近更新 更多