我在使用PhpRenderer时遇到了问题,让我们从上下文开始。我必须生成一堆静态页面来缓存它们(使用文件系统适配器的缓存存储)。因此,我在EVENT_ROUTE上连接了一个事件来提供静态页面(如果存在),并在EVENT_FINISH上连接一个事件以获取响应内容并将其写入缓存文件。它工作得很好。
我的问题是,我想在导航之前生成这些页面(我有大约 300 万个页面要生成)。我的想法是创建一个可以在CLI中调用的控制器,以便能够安排庞大的任务。因此,在我的第二个控制器中,我调用返回我感兴趣的 ViewModel 的控制器,构建渲染器,并呈现我的操作 ViewModel 和布局以获取页面的整个 HTML。
这是代码:
public static function GetStaticResponse(ServiceManager $sm, AbstractActionController $controller, array $routeParams){
$event = new MvcEvent();
$request = new Request();
// $controller = new $controller();
$router = $sm->get('Router');
// Test values!!!
// $routeMatch = new RouteMatch(array('controller' => 'index', 'action' => 'showad', 'ad_id' => '1002293747'));
// Test values end !!
$routeMatch = new RouteMatch($routeParams);
$event->setRouter($router);
$event->setRouteMatch($routeMatch);
$controller->setEvent($event);
$pluginManager = $sm->get('ControllerPluginManager');
$controller->setServiceLocator($sm);
$controller->setPluginManager($pluginManager);
$view = $controller->dispatch($request);
$config = $sm->get('Config');
$renderer = new PhpRenderer($config);
$map = new TemplateMapResolver(
$config['view_manager']['template_map']
);
$renderer->setResolver($map);
$renderer->setHelperPluginManager($sm->get('ViewHelperManager'));
$view->setTemplate('showad');
$content = $renderer->render($view);
$renderer = new PhpRenderer($config);
$map = new TemplateMapResolver(
$config['view_manager']['template_map']
);
$renderer->setResolver($map);
$renderer->setHelperPluginManager($sm->get('ViewHelperManager'));
$viewLayout = new ViewModel();
$viewLayout->setTemplate('layout/layout');
$viewLayout->setVariables(array("content" => $content));
$render = $renderer->render($viewLayout);
unset($event, $request, $router, $routeMatch, $controller, $pluginManager, $view, $config, $renderer, $content, $viewLayout);
return $render;
}
当我只执行一次时,此方法工作正常。当我在循环中再次调用此方法时,渲染器似乎具有一些静态属性,并且每当布局调用"headTitle"或"headLink"等帮助程序时,标题和链接都会一次又一次地附加。
例如:第一个循环
<!DOCTYPE html><html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<link rel="icon" type="image/ico" href="http://apte.local/images/favicon.ico">
<title>title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Le styles -->
<link href="http://apte.local/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
<link href="http://apte.local/css/style.min.css" media="screen" rel="stylesheet" type="text/css">
<link href="http://apte.local/js/jquery/css/ui-lightness/jquery-ui.css" media="screen" rel="stylesheet" type="text/css">
<!-- Scripts -->
第二循环:
<!DOCTYPE html><html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<link rel="icon" type="image/ico" href="http://apte.local/images/favicon.ico">
<title>title - title</title><!-- title generated with headTitle -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- in layout headMeta is used to generate meta -->
<!-- Le styles -->
<link href="http://apte.local/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
<link href="http://apte.local/css/style.min.css" media="screen" rel="stylesheet" type="text/css">
<link href="http://apte.local/js/jquery/css/ui-lightness/jquery-ui.css" media="screen" rel="stylesheet" type="text/css">
<link href="http://apte.local/images/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon"> <!-- in layout headLink helper is used to generate the link -->
<!-- Scripts -->
我不知道我的想法是否正确,我认为使用与单元测试相同的逻辑可以完成这项工作,我错过了什么吗?
我想知道是否有办法触发我已经编码并且在 http 模式下工作正常的事件。
(我已经测试过在EVENT_DISPATCH上连接回声"测试",但我的事件只触发了一次,$controller->dispatch(...) 不会触发当前事件管理器的调度事件。
如果有人有想法,或者遇到过类似的案例,我很乐意阅读您如何解决这个问题。
好吧,我找到了解决这个问题的方法,实际上它来自插件headMeta,headTitle,这些插件使用缓存来存储所有添加的条目(附加,前置或设置)。当实例化新的渲染器或获取当前时,缓存不会重置,当然,在第二次渲染时,更多的条目会添加到当前插件缓存中......所以每次渲染后,都必须清除缓存,以避免多个标题、元等......
我的代码来解决这个问题In ConsoleController::buildStaticCacheAction()
// Following code is in a loop
// Dispatch to get the ViewModel
$view = $this->forward()->dispatch('Application'Controller'Index', array("controller" => "index", "action" => "showad", "ad_id" => $current['adId']));
// Getting renderer
$renderer = $this->getServiceLocator()->get('ViewManager')->getRenderer();
// Render
$html = $renderer->render($view);
//Clear head plugins cache
$renderer->headTitle()->setContainer(new Container());
$renderer->headMeta()->setContainer(new Container());
$renderer->headLink()->setContainer(new Container());
我猜$view->setTemplate('showad')以某种方式搞砸了它。从调度中获得响应后,您可以将其设置为嵌套的 ViewModel 或仅作为新 ViewModel() 的变量,对吗?
关于生成请求,您可以生成控制台请求并创建控制台感知控制器,而不是像单元测试那样引导。