Improving Ajax performance in Zend Framework applications

March 23, 2009 – 7:49 am Tags: , , ,

A common reason to use Ajax in a website is to make it feel faster, so you usually want Ajax requests be processed as quickly as possible.

While there are many ways to speed up Zend Framework based applications, there are still some things like routing and dispatching which still add up to the total.

There is, however, another way to make Ajax work even faster

A french translation of this post by Antoine Delaisse is available at “Le blog du Zend Framework”

Create a separate Ajax handler

Most of the time Ajax code does not need routing, dispatching, plugins and all the usual stuff that runs in a Zend Framework based application.

To get rid of these mostly useless processes, we can create a separate Ajax handler script.

The idea is that instead of calling the main application, we have a separate lean script which is greatly simplified and handles just some selected cases. For example, if we have an Ajax-based search, it will work just fine without a plugin which checks if the user has access to the current page.

It may seem that this will lead to code duplication – indeed it will if your application is poorly designed. For this to be easy to implement, the code needs to be properly separated into reusable classes.

An example on code separation

Let’s take a look at an example, continuing with the idea of having an ajax based search feature. Let’s say we only have a non-ajax based search, and we want to modify our code to have a blazingly fast Ajax-based version of it.

You might have something like this in your code

//Note that this is a simplified example
class SomeController extends Zend_Controller_Action {
  public function searchAction() {
    $db = new Database();
 
    //LIKE may be slow, but this is just an example so it'll do
    $sql = 'SELECT * FROM items WHERE name LIKE ?';
    $results = $db->fetchAll($sql, '%' . $_GET['search'] . '%');
 
    $this->view->results = $results;
  }
}

Now if we wanted to also have a separate script for the search feature, we would have to copy-paste the above code. Instead, we should move the searching code into its own class:

class ItemSearch {
  private $_db = null;
  public function __construct($db) {
    $this->_db = $db;
  }
 
  public function getResults($search) {
    $sql = 'SELECT * FROM items WHERE name LIKE ?';
    $results = $this->_db->fetchAll($sql, '%' . $search . '%');
    return $results;
  }
}

Now, in the actual controller we call this class instead:

public function searchAction() {
  $search = new ItemSearch(new Database());
  $this->view->results = $search->getResults($_GET['search']);
}

An example handler script

Now that we have the searching “business logic” separated into its own class, we can create the search script without having to resort to cooking copy-pasta.

require_once 'bootstrap.php';
 
$results = array();
if(isset($_GET['search'])) {
  $search = new ItemSearch(new Database());
  $results = $search->getResults($_GET['search']);
}
 
//Let's assume the ajax request expects the results in JSON
echo json_encode($results);

In this case the bootstrap.php file would contain common initialization logic: Setting up the database connection, registering an autoloader, and other tasks needed for the ItemSearch to function properly. It would not include setting up the front controller, as that is not needed in the separate handler.

You may wonder why aren’t we just using the controller, which does pretty much the same.

If you think about it, what do you need to get a ZF controller, and the result from it? A lot of other things, like Zend_View, an action helper broker, etc.

For getting a complete list of the various classes you would need for a controller, you could use the packageizer. Just check “Zend_Controller_Action” from “Zend_Controller”.

Summing up

As you can see, the ajax handler script can be extremely simple. This way it avoids all the overhead of the usual Zend Framework related things like routing and dispatching, and can make your sites Ajax requests work very quickly!

This approach can also be used with most other frameworks. You should usually get some more performance out of it.

Share this:
  1. 16 Responses to “Improving Ajax performance in Zend Framework applications”

  2. Very cool post, i was actually thinking of the same thing the other day, and was thinking of building a lite front controller for Ajax Calls.

    By gabriel solomon on Mar 23, 2009

  3. I don’t know if you’ve been tracking my Pastebin app on github, but I’ve been doing precisely this. I also do the same thing for service endpoints (xml-rpc, json-rpc, etc) — in each case, the server component in use is already a controller of sorts, and the “view” is already defined by the protocol being used. Using the MVC is redundant.

    By Matthew Weier O'Phinney on Mar 23, 2009

  4. I had a feeling I had seen someone mention/use this, so perhaps it was you =)

    By Jani Hartikainen on Mar 23, 2009

  5. There is an inconvenience with this approach, developers need to be aware of the diferences between two ‘run-times’. Once they learn it there isn’t much problem but it adds up complexity to having new developers in the project and debugging it.

    In my opinion this should be a last step of optimizations, in case performance is not enough by the use of caches and/or offline data generation.

    By DrSlump on Mar 23, 2009

  6. Great post and thanx for it.

    A question: Normally, all requests are redirected to the index.php file, with the Url-rewriting. How the view will be able to call our ajax handler?

    Thank you in advance.

    By wtc0der on Mar 23, 2009

  7. @wtc0der — usually with this approach, you create new scripts for your service/ajax endpoints somewhere under your public directory. You can either call them by name (which works with the ZF recommended rewrite rules), or create new rewrite rules for them (which is more forward compatible should you choose to move them later).

    By Matthew Weier O'Phinney on Mar 23, 2009

  8. @Matthew – Ok, Thank you very much. My htaccess file did not contain the good rules. Now it’s ok.
    @+

    By wtc0der on Mar 23, 2009

  9. Agree with DrSlump that this could be a measure of last resort, since it introduces some duplication:
    - of entry point (the .php scripts in public directory)
    - of routes, since if you change your routes you also have to change the .htaccess rules;
    I use this approach to output uploaded files (readfile() to prevent execution), but the path is rewrited to the public/static.php entry point to minimize the coupling.

    By Giorgio Sironi on Mar 23, 2009

  10. @Giorgio and @DrSlump
    This doesn’t introduce any duplication…in fact it takes advantage of code which is written in a DRY fashion. Your business layer should not have any knowledge or dependency on ZF at all…precisely for situations like this. ZF is a great presentation framework which gives you a good clean method of creating “screens” in a maintainable manner. But there are many aspects and layers of an application.
    Some applications need cron jobs that run in the background. Some applications have an additional layer for an external RPC/Rest API. There’s no reason why these things need to go through the “VC” stack of ZF.

    By Avi on Mar 23, 2009

  11. Thanks for the post. Coding principles aside, how much “faster” is this than routing through the regular MVC way? I prefer having a bit of additional overhead in the background if the coding maintenance is simpler. Wouldn’t creating a seperate AJAX layer in some ways disorganize the code?

    By andre on Mar 23, 2009

  12. Would prefer to see some benchmarks. The routing produces an overhead. But how much is it really. Like to see the difference.

    By Tom on Mar 23, 2009

  13. @andre and @Tom: I’ll see if I can work up some concrete benchmarks on stuff I’ve done on github. From what I _can_ tell you (I did some benchmarking, but I don’t have the numbers handy), using ZF’s MVC with only opcode caching (no extra caching) typically limits you to around 80 req/s; with a service endpoint, this will often give you > 200 req/s. It’s really a significant difference — and it comes from having fewer resources necessary between request and response (your server class acts as your controller, and the response class acts as your view).

    When it comes to code maintenance, Zend_Application will allow you to share a common bootstrap between your MVC and your service endpoints — which will make long term maintenance and organization easier. Your service endpoint is simply a single script with a single route to it — and you attach your existing service/model classes to the server instance you create. (You should already be putting the bulk of your business logic in your service or model layers as it is, keeping application maintenance trivial.) You don’t need to add extra code to disable layouts and view scripts, which keeps the code uncluttered and _more_ maintainable. All in all, it makes for a more easily maintained architecture, and puts the various contexts you need into discrete locations in your filesystem and on your server.

    By Matthew Weier O'Phinney on Mar 24, 2009

  14. Thats indeed a significant difference. Worth wile too look into then. Im using ZF in combination with Ext JS and use a lot of AJAX req.

    By Tom on Mar 26, 2009

  15. Hi Evryone

    As I had tried to get the chain selection using oracle with respect to parent to child relationship.
    I’m not able to get this using Zend framework, in PHP i’m able to do.
    So if anybody have any idea about this, please help me out.

    Exactly I need is once you select any object in a drop down box automatically it will show the another drop down box with the respective data from oracle.

    Please help me out, if anybody have knows smthng abt it.

    Thanks in advance.

    Best Regards
    Muzeeb

    By muzeeb on Aug 17, 2010

  1. 2 Trackback(s)

  2. Mar 23, 2009: Mar-23-2009 javascript/ajax links | w3feeds
  3. Apr 22, 2009: Améliorer les performances d’AJAX dans les applications Zend Framework | Le blog du Zend Framework

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)