4
\$\begingroup\$

I'm just getting started with AJAX and am unsure of the best way to structure a PHP AJAX handler. I created a PHP file, ajax_handler.php, and the way I have it structured now is just a bunch of if-else statements (one for each AJAX event), like the following.

First, I make sure there's actually a request being made:

if(isset($_GET['req']))
{
    $req = $_GET['req'];
}
else
{
    die('No request.');
}

Then I process the request like this:

if($req == 'doSomething')
{
    // do something
}
else if($req == 'doSomethingElse')
{
    // do something else
}
else if($req == 'doSomethingDifferent')
{
    // do something different
}
else if($req == 'doSomethingMore')
{
    // do something more
}

The above method works, but it becomes a little difficult to navigate when there are dozens upon dozes of cases. Is there a better method?

\$\endgroup\$

2 Answers 2

6
\$\begingroup\$

Lots of if's tend to signal the need for some classes. What are you using for the main routing that's being done by your app? In other words, when you point to domain.com/blog, how does your app know where to go?

One way to do routing is to use a front controller. It parses the request and makes the appropriate calls. From there, you can create classes for each individual controller your app needs. For example, perhaps you have a blog part of your site. Your front controller routes all requests that start with /blog to the BlogController.php class. This class has several methods: show, create, delete, recent, etc. And depending on the url request, the appropriate method is called.

At this point, adding ajax is easy & organized. Say you have implemented comments in PHP, so you have an addComment method on your Blog controller. To turn it into ajax, simply make your ajax request to /blog/comment/add (or whatever route you're currently using to get here). The front controller will point it to the appropriate method in your Blog controller, and now all you need to do is check if the request was ajax (look at the $_SERVER['HTTP_X_REQUESTED_WITH'] variable). If it was, return just the data you need (some success info).

To add new, ajax-only functionality, you can simply add more methods to your controller, and point your ajax request to the appropriate url. Essentially, you'll be using url's to handle your routing, instead of your if-else structure. And why not? That's what a web app is designed to do in the first place.

For more on this type of architecture, check out this really great article from Symfony2's documentation: http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html.

\$\endgroup\$
4
\$\begingroup\$

First, create an interface for controllers, like

interfaces/controller.php

<?php
interface Controller
{
    /**
     * @param  array  $input  The request parameters/data
     * @return mixed  The (userialized) return data
     */
    public function execute($input);
}

Then create one controller file for each request type, eg.

controllers/dosomething.php

<?php
class doSomethingController implements Controller
{
    public function execute($input)
    {
        // do something
        return $result;
    }
}

Now your original script becomes a dispatcher, loading and calling the responsible controller.

ajax_handler.php

<?php
if (!isset($_GET['req'])) {
    header('400 Bad Request');
    exit;
}    

try {
    $req       = $_GET['req'];
    $className = $req . 'Controller';
    $fileName  = __DIR__ . '/controllers/' . strtolower($req) . '.php';
    require_once $fileName;

    $controller = new $className;
    $result = $controller->execute($_REQUEST);
    echo json_encode($result);
} catch(Exception $e) {
    header('404 Not Found');
    exit;
}    

Of course the ajax_handler.php is simplified; you can easily elaborate it to do a more sophisticated error management, but you get the point.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.