Search code examples
phpresturlbackbone.js

Server side implementation for Rest Api


I am learning backbone.js and rest api. There is one thing that is really bugging me. The urlRoot!

I am very much used to AJAX calls where in we provide a file say handleAjaxCall.php containing xmlhttp.open("POST","handleAjaxCall.php",true); which means send the request to handleAjaxCall.php using post method.

In handleAjaxCall.php I use the information sent and save it in my database. But in urlRoot of a model the URL is always confusing; it is like urlRoot:"/books". I figured out that the URL is a logical URL which is created in .htaccess using rewrite module. Am I right? So instead of rewriting I pointed it to an external file say:

url:'./itemInfo/itemListRet.php', or url:'./itemInfo/itemList.json

itemListRet.php has following code

<?php
 $res = "{category:'check',name:'checkname',id:'itemname1'}";
 echo $res;
?>

itemList.json has following information:
{
id:"item1",
name:"name1",
category:"cat1"
}

When I used fetch for the model I did not receive data at all.

In AJAX I write the PHP code to receive data and save it in database. Everywhere I read about REST it says post is to save new, get is to read, put is to update and delete is to delete. But who exactly is handling all this in server and where exactly is the saving taking place? Is it in database?


Solution

  • I am presently writing my own RESTful api from scratch. I'll give you an outline to help you understand the basics.

    htaccess:

    htaccess is known to not have great performance and is limited in routing ability. The only role that htaccess plays is to route requests to a single php file. That php file will be the entry point for the api. I access my api like this: site.com/api so I use this rule to route all /api requests to a php file:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^api/(.*)$ api/index.php [L]
    

    So, any requests for site.com/api are now routed to api/index.php. That file will be responsible for figuring out what data is requests, retrieving it and printing the result.

    index.php

    Typically, a routing system will have a way to write out a path and an instruction about what to do with that path. For example:

    $myRoutes = [
      '/' => 'home.php',
      '/juices' => 'juices.php'
    ];
    
    $route = $_SERVER['REQUEST_URI'];
    //if we have instructions for this route
    if (in_array($route, $myRoutes)) {
      //inlude the route file
      include $myRoutes[$route];
    }
    else {
      //this route is not defined
      echo "Go to a real page. This one doesn't exist."
    }
    

    A complete routing solution will have ways to parse additional things about the url (route params, query string) so that /juices/apple can be handled as apple being an item of the juices collection.

    My api handles routing a bit differently. I chose a more dynamic approach where my script will attempt to instantiate a class based on api/thisParOfTheUrl, so api/juices corresponds to new JuicesController(). This is actually a complicated process and this example very much over-simplifies it, but just think of this approach like this:

    //$controllerName = 'juices'; //extract "juices" from api/juices/apple
    //this class will be autoloaded - autoloading is awesome
    $controller = new $controllerName();
    $data = $controller->handle($request);
    echo $data;
    

    In either approach, it's just the goal to associate a url with the code that is able to get the requested data.

    Verbs

    The request sent to the api will have a verb telling the api what to do with a resource. As there are some newer verbs like PATCH, I won't go into a lot of detail about this as to not conflict with any newer information that may be available. Architecturally, the only thing that you have to know here is that something in the script will recognize the verb and know how to respond based on it. All of my api controllers are extended from a base controller that deny's all requests that are not GET by default. Each controller can override that and make other methods available (pending an authorization check).

    Where does the data go?

    Data can go wherever you want or need it to. Most of my api's resources are stored in the database. One of my resources is actually compiled by searching a file. Any data your server-side language can get or create - you can use. Do what you want.

    RESTful uri's

    As I mentioned, be sure to not think of your uri's as actions. You want to think of the request as either a collection or an item within a collection. You can identify them how you want, but I find id to be best, as the id should never change. Here are some examples.

    api/articles
    api/articles/15
    api/users
    api/user/4
    

    Helpful Frameworks:

    Check out Zend, Symfony, Laravel are very popular (there may be other good options, also). You can google "REST api with __" for each framework and find good results to help you get started if you want to build your own with the use of a framework.

    Your backbone code:

    Live demo (click).

    var modelClass = Backbone.Model.extend({
      initialize: function() {
        this.on('all', function(e) {
          console.log('Event is '+e+' and id is '+this.get('id'));
        });
      },
      url:"itemList.json",
      defaults: {
        id:"def Item",
        name:"def name",
        category:"def cat"
      }
    });
    
    var modelObj1 = new modelClass();
    
    modelObj1.fetch().then(function(resp) {
      foo(resp);
    })
    
    function foo(resp) {
      console.log(resp);
    }
    

    itemList.json

    {
      "id":"item1",
      "name":"name1",
      "category":"cat1"
    }
    

    The urlRoot property just sets up the base part of the request url. Think of how I explained api/juices/apple. If we have a Juices model, the urlRoot could be set as api/Juices. That won't in your sample code because the request will be itemList.json/def%20Item.