1

我对 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 上连接 echo 'test' 但我的事件只触发一次, $controller->dispatch(...) 不会触发当前事件管理器的调度事件。)

如果有人有想法,或者遇到过类似的情况,我会很高兴了解您如何解决这个问题。

4

2 回答 2

1

好吧,我发现了如何解决这个问题,实际上它来自插件 headMeta、headTitle,这些插件使用缓存来存储所有添加的条目(追加、前置或设置)。当实例化一个新的渲染器或获取当前的渲染器时,缓存不会被重置,当然,当第二次渲染时,更多的条目会添加到当前的插件缓存中......所以每次渲染后,必须清除缓存以避免多个标题,元等...

我的代码在 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());
于 2013-10-17T07:13:27.237 回答
0

我猜它 $view->setTemplate('showad') 以某种方式弄乱了它。从调度中获得响应后,您可以将其设置为嵌套的 ViewModel 或只是作为新 ViewModel() 的变量,对吗?

关于生成请求,您可以生成控制台请求并创建控制台感知控制器,而不是像单元测试那样引导。

于 2013-10-16T19:14:01.477 回答