开发者

How to implement Zend routing with Ajax

i am new to zend and i could not find a way to implement Ajax in zend.

In general php, its pretty easy to make an ajax request and show the response in the desired part of our page. But coming to zend, i have no clue how to 开发者_如何学编程do it.

Suppose in my index controller's index.phtml file, i have a button, and when i click on it, i have to make an ajax request to a particular controller and action, and load the related controller action's view in my page.

But what i could not understand is how to specify the urls for the ajax request and how the routing works.

Currently, i made ajax request to load the view statically like this:

xmlhttp.open("GET","../application/views/scripts/register/register.phtml",true);

FYI, i am using regex routing in my application, so would it be better to use curl to route the requests?


First things first, you don't request the view directly. You need to request the specific controller action, eg

/register/register

Zend comes with a great action helper called AjaxContext. This helper lets you respond with a different view based on the type of request (XmlHttpRequest) and a format parameter, disabling any layouts normally present.

To set it up, place something like this in your controller's init() method

public function init()
{
    $this->_helper->ajaxContext->addActionContext('register', 'html')
                               ->initContext();
}

Then, add a view script with the ajax suffix, eg register/register.ajax.phtml.

Construct your AJAX GET request to include the format=html parameter, eg

xmlhttp.open('GET', '/register/register/format/html', true);

or

xmlhttp.open('GET', '/register/register?format=html', true);

What will be returned is the rendered contents of register.ajax.phtml, without any layouts.


Apart from what the other answers stated, there's also a URL view helper function that can be useful to call a specific action on a controller. So you could just use $this->url(array('controller' => 'your_controller', 'action' => 'your_action'), 'default', true); to get the link to "your_action" action on the "your_controller" controller (using the default route). You could also specify a specific route instead of 'default' if you have one defined.

So for your example you would use something like the following in your view phtml file (if you're using the default routing) :

xmlhttp.open("GET","<?php echo $this->url(array('controller' => 'register', 'action' => 'register'), 'default', true);?>");

For more information refer to Zend Framework - View Helpers.


You should never be requesting the view directly. That's just wrong. Request URI like this:

xmlhttp.open("GET","/register/register");

Which means "I am looking for default module, register controller and register action", or in other words RegisterController::registerAction().

It's the same as:

xmlhttp.open("GET","/default/register/register");

Which is the same, the default module can be omitted.

Zend Framework knows where to look for the view script (unless you are using some unusual directory structure).

You can just create a blank layout and use it for your ajax controller actions (or what Phil suggested, AjaxContent is probably better for this).


I'll write here an almost complete "how to" guide to implement AJAX calls in Zendframework 3. We need:

  1. A route declaration
  2. A controller
  3. Some javaScript (is out of skope, perhaps I'll show it in other place)

The route declaration:

<?php
// editing a module.config.php in your project
// typical lines:
namespace Ajax2l; // my ajax module name
use Zend\Router\Http\Segment;
// ...
'router' => [
  // ... other routes
  'ajax2lsajaxcall'    => [
    'type'    => Segment::class,
    'options' => [
        'route' => '/ajax2l/ajaxrequest[/:action][/:garbage]',
        // the :action wildcard is a place to have extra parameters
        // the :garbage wildcard is a place to send random strings
        //      to ensure you break cache to get real process for
        //      all your calls, since every call will be different
        'defaults' => [
            'controller' => Controller\AjaxController::class,
            'action'     => 'ajaxrequest'                        
        ]
    ],
    'may_terminate' => true,
    'child_routes'  => [
      // other ajax routes if needed
    ]
],
// I only use one ajax route and one controller for all my sites' ajax 
// calls because they fire small db actions and reflect them on small
// parts of my pages. So I think I do not need a route and a controller
// for each ajax call. Instead, I use a Library and some services to get
// sets of elementary components and to perform tasks.

The Controller My Ajax2l module is located under "myzend_project/module" directory.

<?php
// Filename: /module/Ajax2l/src/Controller/AjaxController.php
namespace Ajax2l\Controller

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
// No more components are needed

class AjaxController extends AbstractActionController {
  public function ajaxrequestAction(){
    $request = $this->getRequest();
    $content = $request->getContent();
    $isHttpRequest = $this->ifIsValidHttpRequest();
    // if you have a real ajax call you must disable the normal output
    $viewmodel = new ViewModel();
    $viewmodel->setTerminal($is_xmlhttprequest);
    // If not an Ajax call (perhaps from untrusted eyes) serve a forgiven
    // page message
    if(!$isHttpRequest){
      return $this->forgivenPage();
    }
    // Now prepare a response and responds
    $requestParams = $this->preProcessRequest($content);
    // call the logics to process your params
    $output = $this->processRequestParams($requestParams);
    // and send a response
    $response = $this->getResponse();
    $response->setContent($output);
    return $response;
  }

  private function ifIsValidHttpRequest($content){
    // I use a small token string to verify if posted data matches 
    // perhaps not the proper way but is fast and works
    $token = 'my_secure_visitor_session_token_identifier';
    return (strpos($content, $token) > 2) ? 1 : 0;
    // the validation is simplified here it has some more
    // complex logics. To ensure validation of requesting source
  }

  private function preProcessRequest($content){
    // The logics to know what to do
    // ...
    // here you can identify and set properly the post params
  }

  function processRequestParams($requestParams){
    // some logics to process your data
    // ...
    // some logics to create a Json output
    // ...
    return $jsonObject;
  }

  protected function forgivenPage(){
    $view = new ViewModel([]);
    // set a forgiven message page as output
    $view->setTemplate('ajax2l/messages/forgiven.phtml');
    // note: the views directory uses lowercase for module names
    return $view;
  }
}

Hope it helps. I lost a lot of time reading on zend ajax without results. So I hope I was the last losing his time on this topic.

Luis

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜