мы сталкиваемся со странным поведением приложения Zend Expressive, использующего Zend View и работающего на http-сервере swoole.Это поведение связано с шаблоном Singleton.
Мы настроили Zend Expressive для запуска на http-сервере swoole - https://docs.zendframework.com/zend-expressive-swoole/ - и все запрограммированные API-интерфейсы работают без проблем (swoole - это ракета!)
Но мы попытались перейти к следующему шагу и попытались запустить веб-интерфейс через http-сервер swoole.
Там мы нашли странное поведение.Чтобы упростить мой вопрос (мы используем много помощников вида), наши веб-интерфейсы работают с Zend View и используют помощник headTitle.Когда вы загружаете веб-интерфейс в первый раз, все работает хорошо, но при перезагрузке страницы вы видите, что мета-заголовок дублирован.
Наш следующий обработчик
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, мы увидели, что у нас возникла другая проблема, потому что решение было реализовано в коде, и все запросы к apis были правильными
в zend-expressive-swoole / src / ConfigProvider.php youможет видеть
ServerRequestInterface::class => ServerRequestSwooleFactory::class,
Затем мы меняем нашу точку зрения и осматриваем помощники Zend View, и мы обнаружили, что HeadTitle представления помощника простирается от контейнера \ 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 используется снова и снова.
Сталкивались ли вы с этой проблемой?Как вы решили это?
Мы думаем о создании настраиваемого помощника для удаления всех контейнеров помощников вида, но если мы сделаем это, мы должны изменить множество файлов представления, чтобы добавить этого нового и настраиваемого помощника.
Заранее спасибо