ZF3:如何从控制器中的另一个动作中获取一个动作的视图?

ZF3: How to get view of an action from another action in the controller?

在我的控制器动作中,我想抓取另一个动作的渲染整页:

class MycontrollerController extends AbstractActionController
{
    public function firstactionAction()
    {
         $html = some_function_to_get_the_rendered_page_of_secondaction();
    }

    public function secondactionAction()
    {
         return new ViewModel();
    }
}

谨慎使用setTemplate()

MycontrollerControllerFactory.php

<?php

namespace Application\Controller\Service;

use Application\Controller\MycontrollerController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class MycontrollerControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $controller = new MycontrollerController();
        $controller->setRenderer($container->get('Zend\View\Renderer\PhpRenderer'));
        return $controller;
    }
}

MycontrollerController.php

<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class MycontrollerController extends AbstractActionController
{
    /**
     * @var \Zend\View\Renderer\PhpRenderer
     */
    protected $renderer;

    /**
     * @return \Zend\View\Renderer\PhpRenderer
     */
    public function getRenderer()
    {
        return $this->renderer;
    }

    /**
     * @param  \Zend\View\Renderer\PhpRenderer $renderer
     * @return self
     */
    public function setRenderer($renderer)
    {
        $this->renderer = $renderer;
        return $this;
    }

    public function firstAction()
    {
        if ($this->yourMethod()) {
            $secondView = $this->secondAction();
            $html = $this->getRenderer()->render($secondView);
        }

        $view = new ViewModel();
        $view->setTemplate('namespace/my-controller/first');
        return $view;
    }

    public function secondAction()
    {
        $view = new ViewModel();
        $view->setTemplate('namespace/my-controller/second');
        return $view;
    }
}

所以,我建议创建一个新插件 'htmlRender' :

module.config.php

'controller_plugins' => [
    'factories' => [
        'htmlRender' => Application\Mvc\Controller\Plugin\Service\HtmlRenderFactory::class,
    ],
],

HtmlRenderFactory.php

<?php
namespace Application\Mvc\Controller\Plugin\Service;

use Application\Mvc\Controller\Plugin\HtmlRender;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\View\Renderer\PhpRenderer;

class HtmlRenderFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $plugin = new HtmlRender();
        $plugin->setRenderer($container->get(PhpRenderer::class));
        return $plugin;
    }
}

HtmlRender.php

<?php
namespace Application\Mvc\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\View\Renderer\RendererInterface;

class HtmlRender extends AbstractPlugin
{
    /**
     * @var \Zend\View\Renderer\PhpRenderer
     */
    protected $renderer;

    /**
     * @param  string|\Zend\View\Model\ModelInterface $nameOrModel
     * @param  null|array|\Traversable $values
     * @param  string|bool|\Zend\View\Model\ModelInterface $layout
     * @return string
     */
    public function __invoke($nameOrModel, $values = null, $layout = false)
    {
        $content = $this->getRenderer()->render($nameOrModel, $values);
        if (!$layout) {
            return $content;
        }

        if (true === $layout) {
            $layout = 'layout/layout';
        }
        return $this->getRenderer()->render($layout, [
            'content' => $content,
        ]);
    }

    /**
     * @return \Zend\View\Renderer\PhpRenderer
     */
    public function getRenderer()
    {
        return $this->renderer;
    }

    /**
     * @param  \Zend\View\Renderer\PhpRenderer|RendererInterface $renderer
     * @return self
     */
    public function setRenderer(RendererInterface $renderer)
    {
        $this->renderer = $renderer;
        return $this;
    }
}

在MycontrollerController.php

中使用
<?php
class MycontrollerController extends AbstractActionController
{
    public function firstAction()
    {
        if ($this->yourMethod()) {
            // Option 1 without layout
            $html = $this->htmlRender($secondView);
            // Option 2 without layout
            $html = $this->htmlRender('namespace/my-controller/second', $yourVariables));

            // Option 1 with layout
            $html = $this->htmlRender($secondView, null, true);
            //$html = $this->htmlRender($secondView, null, 'layout/my-custom-layout');
            // Option 2 with layout
            $html = $this->htmlRender('namespace/my-controller/second', $yourVariables, true));
            //$html = $this->htmlRender('namespace/my-controller/second', $yourVariables, 'layout/my-custom-layout');
        }

        $view = new ViewModel();
        $view->setTemplate('namespace/my-controller/first');
        return $view;
    }

    public function secondAction()
    {
        $view = new ViewModel();
        $view->setTemplate('namespace/my-controller/second');
        return $view;
    }
}