Zend框架2:Ajax调用自动禁用布局(Zend Framework 2: Auto disabl

2019-07-03 11:48发布

一个Ajax请求的我的控制器动作之一返回当前整个页面的HTML。

我只希望它为特定的操作返回HTML(一个.phtml内容)。

下面的代码很差解决通过手动禁用用于特定动作的布局问题:

    $viewModel = new ViewModel();
    $viewModel->setTerminal(true);
    return $viewModel;

我怎样才能让我的应用程序自动禁用布局中检测到AJAX请求时? 我需要为此编写自定义的策略? 如何做到这一点任何意见是非常赞赏。

此外,我试过下面的代码在我的应用程序Module.php - 它被正确地检测AJAX但setTerminal()不禁止的布局。

public function onBootstrap(EventInterface $e)
{
    $application = $e->getApplication();
    $application->getEventManager()->attach('route', array($this, 'setLayout'), 100);

    $this->setApplication($application);

    $this->initPhpSettings($e);
    $this->initSession($e);
    $this->initTranslator($e);
    $this->initAppDi($e);
}

public function setLayout(EventInterface $e)
{
    $request = $e->getRequest();
    $server  = $request->getServer();

    if ($request->isXmlHttpRequest()) {
        $view_model = $e->getViewModel();
        $view_model->setTerminal(true);
    }
}

思考?

Answer 1:

事实上,最好的办法是写另一个策略。 有一个JsonStrategy它可以自动检测accept头自动返回JSON格式的,但与Ajax的呼吁fullpages,有它的好,它并不会自动做的事情,因为你可能希望得到一个完整的页面。 上述方案中你提到的将是快速的路要走。

当去全速,你只能有一个附加行。 它总是从你的控制器内返回完全合格的ViewModels的最佳做法。 喜欢:

public function indexAction() 
{
    $request   = $this->getRequest();
    $viewModel = new ViewModel();
    $viewModel->setTemplate('module/controller/action');
    $viewModel->setTerminal($request->isXmlHttpRequest());

    return $viewModel->setVariables(array(
         //list of vars
    ));
}


Answer 2:

我认为这个问题是你调用setTerminal()在视图模型$e->getViewModel()是负责渲染的布局 ,而不是行动。 你必须创建一个新的视图模型,调用setTerminal(true) ,并将其返回。 我使用一个专用的Ajax控制器,所以没有必要确定该动作是否是阿贾克斯与否:

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

class AjaxController extends AbstractActionController
{
    protected $viewModel;

    public function onDispatch(MvcEvent $mvcEvent)
    {
        $this->viewModel = new ViewModel; // Don't use $mvcEvent->getViewModel()!
        $this->viewModel->setTemplate('ajax/response');
        $this->viewModel->setTerminal(true); // Layout won't be rendered

        return parent::onDispatch($mvcEvent);
    }

    public function someAjaxAction()
    {
        $this->viewModel->setVariable('response', 'success');

        return $this->viewModel;
    }
}

在AJAX / response.phtml只需以下几点:

<?= $this->response ?>


Answer 3:

这里是最好的解决方案(愚见)。 我花了差不多两天的时间弄明白。 关于发布在互联网上,没有人到目前为止,我认为。

public function onBootstrap(MvcEvent $e)
{
    $eventManager= $e->getApplication()->getEventManager();

    // The next two lines are from the Zend Skeleton Application found on git
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    // Hybrid view for ajax calls (disable layout for xmlHttpRequests)
    $eventManager->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController', MvcEvent::EVENT_DISPATCH, function(MvcEvent $event){

        /**
         * @var Request $request
         */
        $request = $event->getRequest();
        $viewModel = $event->getResult();

        if($request->isXmlHttpRequest()) {
            $viewModel->setTerminal(true);
        }

        return $viewModel;
    }, -95);

}

我还是不太满意,虽然。 我想创建一个插件作为一个听众,并通过配置文件,而不是onBootstrap方法来配置它。 但是,我会让这为下一次= P



Answer 4:

我回答这个问题,似乎它可能类似- 访问视图模型上的调度事件变量

附加一个事件回调到dispatch事件触发。 一旦这个事件触发它应该让你通过调用来获得操作方法的结果$e->getResult() 在返回视图模型的动作的情况下,它应该让你做setTerminal()修改。



Answer 5:

aimfeld解决方案对我的作品,但在某些情况下,你使用模板的位置试验的问题,试图指定模块:

 $this->viewModel->setTemplate('application/ajax/response');


Answer 6:

最好是使用JsonModel返回好的JSON和关闭布局和视图为您服务。

public function ajaxCallAction()
    {
        return new JsonModel(
            [
                'success' => true
            ]
        );
    }


Answer 7:

我收到这个问题,这里是一个quikc招解决了。

首先,在布局文件夹中创建一个空的布局module/YourModule/view/layout/empty.phtml

你应该只能随声附和此布局中的视图内容这样<?php echo $this->content; ?> <?php echo $this->content; ?>

现在,在您的Module.php设置控制器布局,布局/空的Ajax请求

namespace YourModule;
use Zend\Mvc\MvcEvent;

class Module {
    public function onBootstrap(MvcEvent $e) {
        $sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
        $sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
            if ($e->getRequest()->isXmlHttpRequest()) {
                $controller = $e->getTarget();
                $controller->layout('layout/empty');
            }
        });
    }
}


Answer 8:

public function myAjaxAction() 
{
    ....
    // View - stuff that you returning usually in a case of non-ajax requests
    View->setTerminal(true);
    return View;
}


文章来源: Zend Framework 2: Auto disable layout for ajax calls