preview

Working with RESTful Services in CodeIgniter

CodeIgniter is becoming well known for its power as a PHP based web application framework, but it’s not often that we see examples of it being used for anything else. Today we’ll learn how we can use CodeIgniter to create a RESTful API for your existing web applications, and demonstrate how to interact with your own API or other RESTful web-services, such as Facebook and Twitter.

Tutorial Details

Introduction

If you have been following the CodeIgniter From Scratch series you will know by now that it is relatively quick and easy to put together simple web applications, such as blogs, CMS systems, brochure sites, etc. One thing you may not have thought about is using CodeIgniter to create an interactive API. After trying several existing REST implementations, I found they not only lacked simplicity but were missing most of the features you would expect from a RESTful implementation; so I built my own. This tutorial will show you how to use this code to set up your REST API, and gives example of how to interact with it from your web application.

Assumptions

  1. You have a web server set up, locally or online and known how to manage files on it.
  2. You have read a few of the CodeIgniter from Scratch tutorials.
  3. You know how to set up CodeIgniter.
  4. You know a little about RESTful services.

This tutorial is broken down into two parts. We will start by learning how to create a RESTful service, then further down, we will learn how to interact with it in a few different ways.

Part 1 – Creating a RESTful API

Step 1: Setting up the Demo

Firstly you need to download the codeigniter-restserver code from GitHub and extract it and move the code to your server.

When you open the folder, you will see an entire CodeIgniter install, which is there to power the demo. This allows people to have a play with the REST demo before integrating with your existing application.

Open up “application/config/config.php” and set the base_url to get links working. This base_url will be different for everyone and depends entirely on where you uploaded your files.

Step 2: The URLs

With the files extracted and the base_url set, we are ready to load up our RESTful CodeIgniter installation, and have a look at the demo supplied with it. Browse the base URL, which by default is:

http://localhost/restserver

Here you will find a few example links to the example_api controller, which can be found at “application/controllers/example_api.php”. Let’s dissect the URL’s of these examples to see what is going on. The first URL is a very simple one.

This URL looks very much like any other CodeIgniter URL with a controller and a method, but you will notice in this diagram that the method is named a “Resource”. REST is all about Resources and they are essentially a noun within your application, which are interacted with (i.e added, deleted, edited, queried) based on HTTP headers and URL query strings or HTTP arguments.

The default format for output is XML which is what we see in this basic example. The other links are slightly larger and demonstrate how to pass parameters and show how the output format can be modified in the URL:

Normally in CodeIgniter, you just pass in parameter values, but a REST controller accepts any number of parameters in any order. For this to work, we need to pass in the name of the parameter followed by the value in pairs.

At the end of the URL is the “format” parameter. This is a reserved parameter that will modify the output format of the requested data like so:

By giving both the API developer and the client application the choice of data formats to use, the API is opened up to a much wider audience and can be used with more programming languages and systems. These three are not the only formats supported, out of the box your REST API can use:

  • xml – almost any programming language can read XML
  • json – useful for JavaScript and increasingly PHP apps.
  • csv – open with spreadsheet programs
  • html – a simple HTML table
  • php – Representation of PHP code that can be eval()’ed
  • serialize – Serialized data that can be unserialized in PHP

While adding the format to the URL is not technically the most RESTful way to change formats, it allows for easy browser testing and lets developers without cURL perform simple GET requests on the API. The more RESTful way is to send a Content-type HTTP header to the REST controller using cURL, but that will be explained later.

Step 3: The Code

Now if you open up application/controllers/example_api.php you will immediatley spot a few differences from normal CodeIgniter controllers.

REST_Controller

In the MVC pattern, a controller is the central point of the logic. It is called when a user makes a request and then based on the logic in the controller it fetches data and outputs views. CodeIgniter contains its own logic for how a Controller should work, but as we are doing something different we need our own REST_Controller library to contain its own REST related logic. So instead of simply using:

<?php
class Example_api extends Controller {

}

…you will need to use:

<?php
require(APPPATH'.libraries/REST_Controller.php');

class Example_api extends REST_Controller {

}

Working with Resources

Now your empty controller is set up, next are the methods or “resources”. This is prossibly the most confusing part of the tutorial if you are used to how CodeIgniter works. Basically, you take the Resource and the HTTP verb and combine them to make a method name. So the two examples we looked at before had a Resource of user and users. Because both of these were loaded in the browser, we know it was using a GET request and so the two methods below are used:

<?php
require(APPPATH'.libraries/REST_Controller.php');

class Example_api extends REST_Controller {

    function user_get()
    {
		// respond with information about a user
    }
    
    function users_get()
    {
		// respond with information about several users
    }
}

This may seem a little strange, but it gives you the ability to use the same URL and respond to the request depending on the HTTP verb that has been used. If somebody tries to access your API in a way that is not allowed (in this example PUT or DELETE) it will simply respond with a 404. If you aren’t sure about HTTP verbs, let me explain.

GET

Used to fetch information about an existing resource. This is used by browsers when you enter a URL and hit go, or when you click on a link, so it perfect for fetching information on one of your REST resources (like user).

POST

Used to update an existing resource with information. Browsers use this to submit most types of forms on the internet, although some use GET as well by submitting the form action with a query string containing the field data.

PUT

Less commonly used and not supported by most browsers, PUT is used to create a new resource.

DELETE

Also not used by many browsers, this HTTP verb rather obviously is used to delete a resource.

If we put that into code and allow each verb on the resource user it would look like this:

<?php
require(APPPATH'.libraries/REST_Controller.php');

class Example_api extends REST_Controller {

    function user_get()
    {
		// respond with information about a user
    }

    function user_put()
    {
		// create a new user and respond with a status/errors
    }

    function user_post()
    {
		// update an existing user and respond with a status/errors
    }

    function user_delete()
    {
		// delete a user and respond with a status/errors
    }
}

Accessing parameters and returning data

So now the API has been given its structure by setting up the resources and defining a method for each HTTP verb we wish to support; we need parameters so we can use our CodeIgniter models and libraries. This is one of the major benefits of using CodeIgniter for our API, as we can use our existing models and libraries and not have to re-code them.

<?php
require(APPPATH'.libraries/REST_Controller.php');

class Example_api extends REST_Controller {

    function user_get()
    {
		$data = array('returned: '. $this->get('id'));
		$this->response($data);
    }
    
    function user_post()
    {		
		$data = array('returned: '. $this->post('id'));
		$this->response($data);
    }

    function user_put()
    {		
		$data = array('returned: '. $this->put('id'));
		$this->response($data;
    }

    function user_delete()
    {
		$data = array('returned: '. $this->delete('id'));
		$this->response($data);
    }
}

This example contains five new pieces of code:

$this->get()

Is used to return GET variables from either a query string like this index.php/example_api/user?id=1 or can be set in the more CodeIgniter’esque way with index.php/example_api/user/id/1.

$this->post()

Is an alias for $this->input->post() which is CodeIgniter’s method to access $_POST variables with XSS protection.

$this->put()

Reads in PUT arguments set in the HTTP headers or via cURL.

$this->delete()

You guessed it, this reads in DELETE arguments, also set in HTTP headers or via cURL.

$this->response()

Sends data to the browser in whichever data format has been requested, or defaults to XML. You can optionally pass a HTTP status code to show it has worked or failed. E.g if the ID provided was not in the database, you could use $this->response(array(‘error’ => ‘User not found.’), 404);

Step 4: Working with your Models

Until now, we have been working with an example API in a clean install. So the next step is to get a REST API running from your existing codebase.

Although the download comes with a full CodeIgniter installation for the demo and to allow API’s to be built from scratch, the only two files of importance are:

  1. application/config/rest.php
  2. application/libraries/REST_Controller.php

Drop those two files into your CodeIgniter application and create a new API controller.

<?php
require(APPPATH.'/libraries/REST_Controller.php');

class Api extends REST_Controller
{
	function user_get()
    {
        if(!$this->get('id'))
        {
        	$this->response(NULL, 400);
        }

        $user = $this->user_model->get( $this->get('id') );
    	
        if($user)
        {
            $this->response($user, 200); // 200 being the HTTP response code
        }

        else
        {
            $this->response(NULL, 404);
        }
    }
    
    function user_post()
    {
        $result = $this->user_model->update( $this->post('id'), array(
        	'name' => $this->post('name'),
        	'email' => $this->post('email')
        ));
        
        if($result === FALSE)
        {
        	$this->response(array('status' => 'failed'));
        }
        
        else
        {
        	$this->response(array('status' => 'success'));
        }
        
    }
    
    function users_get()
    {
        $users = $this->user_model->get_all();
        
        if($users)
        {
            $this->response($users, 200);
        }

        else
        {
            $this->response(NULL, 404);
        }
    }
}
?>

This shows an example API with some generic model names. In the first method, we are picking up a ?id=XX and passing it to the model. If data is found we send it to the $this->response() function with a status 200. If nothing is found, return no body and a 404 to say nothing was found. You can imagine how this could be expanded to run all sorts of API activities for your web application.

Step 5: Securing the API

Now your API is built it needs securing so only users given access can interact with the API. To set the login type, usernames and passwords open up “application/config/rest.php” inside your codebase.

/*
|--------------------------------------------------------------------------
| REST Login
|--------------------------------------------------------------------------
|
| Is login required and if so, which type of login?
|
|	'' = no login required, 'basic' = relatively secure login, 'digest' = secure login
|
*/
$config['rest_auth'] = 'basic';

None

Anyone can interact with any one of of your API controllers.

Basic

A relatively insecure login method which should only be used on internal/secure networks.

Digest

A much more secure login method which encrypts usernames and password. If you wish to have a protected API which anyone could get at, use digest.

/*
|--------------------------------------------------------------------------
| REST Login usernames
|--------------------------------------------------------------------------
|
| Array of usernames and passwords for login
|
|	array('admin' => '1234')
|
*/
$config['rest_valid_logins'] = array('admin' => '1234');

Setting up the users is simple. Each login is an array item, with a key and a value. The key is the username and the value is the password. Add as many as you like to this array and dish them out to anyone who will be using the API.

Part 2 – Interacting with RESTful Services

Whether it is the API you have just built or a public service such as Twitter, you will want to be able to interact with it somehow. Seeing as RESTful services work with basic HTTP requests it is very easy to do this in a number of different ways.

Different Methods to Interact with REST

Each of these different interaction methods will be shown with the code placed directly in the Controller methods. This is purely so the demos are easier to read and would normally would be placed inside a model or a library for correct MVC separation.

file_get_contents()

Using the very simple PHP function file_get_contents(), you can perform a basic GET request. This is the most basic of all the methods but is worth mentioning for those “quick and dirty” moments.

$user = json_decode(
	file_get_contents('http://example.com/index.php/api/user/id/1/format/json')
);

echo $user->name;

It’s worth noting that, while this method will not work using HTTP Digest authentication, if you are using HTTP Basic authentication you can use the following syntax to get data from your password protected RESTful API:

$user = json_decode(
	file_get_contents('http://admin:1234@example.com/index.php/api/user/id/1/format/json')
);

echo $user->name;

There are a few problems with using this method: the only way to set extra HTTP headers is to set them manually using the PHP function stream_context_create(), which can be very complicated for developers who are new to the internal workings of HTTP requests. Another disadvantage is that you only receive the body of the HTTP response in its raw format, which means you need to handle conversion from very single request.

cURL

cURL is the most flexible way to interact with a REST API as it was designed for exactly this sort of thing. You can set HTTP headers, HTTP parameters and plenty more. Here is an example of how to update a user with our example_api and cURL to make a POST request:


    function native_curl($new_name, $new_email)
    {
	    $username = 'admin';
		$password = '1234';
		
		// Alternative JSON version
		// $url = 'http://twitter.com/statuses/update.json';
		// Set up and execute the curl process
		$curl_handle = curl_init();
		curl_setopt($curl_handle, CURLOPT_URL, 'http://localhost/restserver/index.php/example_api/user/id/1/format/json');
		curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl_handle, CURLOPT_POST, 1);
		curl_setopt($curl_handle, CURLOPT_POSTFIELDS, array(
			'name' => $new_name,
			'email' => $new_email
		));
		
		// Optional, delete this line if your API is open
		curl_setopt($curl_handle, CURLOPT_USERPWD, $username . ':' . $password);
		
		$buffer = curl_exec($curl_handle);
		curl_close($curl_handle);
		
		$result = json_decode($buffer);

		if(isset($result->status) && $result->status == 'success')
		{
			echo 'User has been updated.';
		}
		
		else
		{
			echo 'Something has gone wrong';
		}
    }

Interacting with your API this way works fine, but there are two problems with this method:

  1. It uses an ugly confusing syntax – imagine creating several an application based on that.
  2. cURL is not installed on all servers by default.

To solve this ugly syntax, a cURL library has been developed for CodeIgniter which simplifies things immensely.

The exact same request made with the cURL library would look like this:

    function ci_curl($new_name, $new_email)
    {
	    $username = 'admin';
		$password = '1234';
		
		$this->load->library('curl');
		
		$this->curl->create('http://localhost/restserver/index.php/example_api/user/id/1/format/json');
		
		// Optional, delete this line if your API is open
		$this->curl->http_login($username, $password);

		$this->curl->post(array(
			'name' => $new_name,
			'email' => $new_email
		));
		
		$result = json_decode($this->curl->execute());

		if(isset($result->status) && $result->status == 'success')
		{
			echo 'User has been updated.';
		}
		
		else
		{
			echo 'Something has gone wrong';
		}
    }

Much nicer to look at right? Well there is an even easier method to work with REST in your CodeIgniter applications that this.

REST client library

A REST client library has been developed that sits on top of this cURL library which handles format conversion, HTTP logins and several other aspects of your REST API.

    function rest_client_example($id)
    {
		$this->load->library('rest', array(
			'server' => 'http://localhost/restserver/index.php/example_api/',
			'http_user' => 'admin',
			'http_pass' => '1234',
			'http_auth' => 'basic' // or 'digest'
		));
		
        $user = $this->rest->get('user', array('id' => $id), 'json');
        
        echo $user->name;
    }

Here you can see we are making a GET request, sending id as a parameter and telling the library we want ‘json’ as the content format. This handles the setting of Content-type for you, and converts the data into a PHP object for you. You can change this value to ‘xml’, ‘json’, ‘serialize’, ‘php’, ‘csv’ or any custom MIME-type you like, for example:

	$user = $this->rest->get('user', array('id' => $id), 'application/json');

As you have probably guessed as well as $this->rest->get(), the library also supports $this->rest->post(), $this->rest->put(), $this->rest->delete() to match all of your REST_Controller methods.

You will need to var_dump() results coming from the REST client library to make sure you are getting the right data format back. The conversion will somtimes be array and sometimes be an object, depending on how it is converted by PHP. If the returned MIME-type is not supported then it will simply return the format as plain-text.

Talking to Twitter

Using this REST library you can talk other RESTful services such as Twitter and Facebook. Here is a simple example of how you can get details for a specfic user based on their ID, using Twitter’s default format XML.

        $this->load->library('rest', array('server' => 'http://twitter.com/'));
		
        $user = $this->rest->get('users/show', array('screen_name' => 'philsturgeon'));
        $this->load->library('rest', array(
        	'server' => 'http://twitter.com/',
			'http_user' => 'username',
			'http_pass' => 'password',
			'http_auth' => 'basic'
        ));
		
        $user = $this->rest->post('statuses/update.json', array('status' => 'Using the REST client to do stuff'));

Looking at this, you will notice that interacting with the Twitter API is a bit different in a few ways.

  1. They support URL based format switching in the form of .json instead of /format/json. Some require an extension, some do not; so it’s best to always add them.
  2. They mostly only support GET/POST, but are starting to add more DELETE methods
  3. They don’t always have just a resource in their URL, for example: users/search is one REST method, but lists is another.

Keep an eye out for these differences as they can catch you out. If you get stuck, simply echo $this->rest->debug() for a whole range of information on your REST request.

Summary

Combining what you now know about RESTful services, the CodeIgniter REST client library and the Twitter API documentation – or any other RESTful API documentation for that matter – you can create some very powerful applications that integrate with any custom or public web service using REST. You can extend your API by creating more REST_Controller’s and even make a modular API by using Matchbox or Modular Separation to create an api.php controller for each module to help keep your API as neatly organized as your application.

Write a Plus Tutorial

Did you know that you can earn up to $600 for writing a PLUS tutorial and/or screencast for us? We’re looking for in depth and well-written tutorials on HTML, CSS, PHP, and JavaScript. If you’re of the ability, please contact Jeffrey at nettuts@tutsplus.com.

Please note that actual compensation will be dependent upon the quality of the final tutorial and screencast.

Write a PLUS tutorial

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • vamshi

    thank you

  • http://codecanyon.net/item/tiny-rest-framework/99263 Phil Sturgeon
    Author

    For anyone interested in a standalone version of this framework, I put one on CodeCanyon which works almost identically.

    http://codecanyon.net/item/tiny-rest-framework/99263

  • Chandu

    Help needed on Form Validations using REST API.
    Here I am trying to validate the username and password using form_validation library which is
    in build in CodeIgniter. but is not working. Can u guys help……………….

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      “It’s not working” is the bane of any web developers existence.

      What is not working?
      What are you trying?
      Any error messages?

      If you use anything other than POST then Form_validation won’t know what’s going on.

  • http://blunk.com.ar Blunk

    Im wondering where I should modify the controller so the usernames are checked with a DB.
    Right now I modified _check_login and _prepare_basic_auth and works perfectly with basic auth, but I cant get it to work with _prepare_digest_auth. Somehow the response is not valid.

    Any idea? Any other RESTserver controller I can try?

  • Alex Munk

    http://localhost/restserver/example_api/user causes two errors:

    Severity: 8192
    Message: Function set_magic_quotes_runtime() is deprecated
    Filename: codeigniter/CodeIgniter.php
    Line Number: 60

    Severity: 8192
    Message: Assigning the return value of new by reference is deprecated
    Filename: libraries/Loader.php
    Line Number: 255

    I commented out codeigniter/CodeIgniter.php line 60, and the first error went away.

    But something tells me that this is not a great approach. Should I be updating CodeIgniter itself or something?

    • Alex Munk

      I pulled config/rest.php and application/libraries/REST_Controller.php into CodeIgniter version 1.7.2 and these issues went away. The REST_Controller appears to work fine.

      • http://philsturgeon.co.uk Phil Sturgeon
        Author

        Good spot, the version bundled is 1.7.1 which is not compatible with PHP 5.3. I’ll update that tonight.

  • Jeffrey Lui

    Great framework: simple and easy to use.

    One thing I ran into is that because I want to retain CI to use segment instead of query URL style — because it messes up the convention I have already adopted throughout the code base, plus the important fact that CI URL helper classes can’t be used because it’s segment based — I have to tweak the get function in your client library file, Rest.php, a little to not use “?”. Maybe this will be helpful for others:

    public function get($uri, $params = array(), $format = NULL)
    {
    if(!empty($params))
    {
    // NOTE: this does not work well with CI segment-base URI
    //$uri .= ‘?’.http_build_query($params);
    foreach ( $params as $k => $v )
    {
    $uri .= ‘/’ . $k . ‘/’ . $v;
    }
    }
    return $this->_call(‘get’, $uri, NULL, $format);
    }

    • http://philsturgeon.co.uk Phil Sturgeon
      Author

      It uses $this->uri->uri_to_assoc() to use pairs of keys. The URI helper is perfectly happy to let you send values in the form of:

      /key1/value1/key2/value2/

      I’m not sure what your client lib tweak would do differently. You can send a GET variable via /foo/bar or ?foo=bar and they will both work the same.

      I think you might be confusing yourself a little bit. :-)

  • Chris Rueber

    I just wanted to say thank you! For bringing REST to the PHP/CodeIgniter world!

  • Chris Rueber

    Howdy again!

    I just figured that I would share my code with you, since I was trying to be RESTfully accurate in my response codes as possible. Here are my three function replacements for your REST_Controller, if you care to show them to others!

    function _remap($object_called)
    {
    $controller_method = $object_called.’_’.$this->_method;

    if(method_exists($this, $controller_method)) {
    $this->$controller_method();
    }
    else {
    if ($this->_do_any_methods_exist($object_called)) {
    $this->response( NULL, 405 ); // method not allowed
    }
    else {
    $this->response(); // will throw a 404.
    }
    }
    }

    function _do_any_methods_exist($obj) {
    $methods = array(“get”, “post”, “put”, “delete”);

    foreach ($methods as $method) {
    $controller_method = $obj . ‘_’ . $method;
    if(method_exists($this, $controller_method)) {
    return true;
    }
    }
    return false;
    }

    function response($data = array(), $http_code = 200)
    {
    if(empty($data))
    {
    if ($http_code != 200) {
    $this->output->set_status_header($http_code);
    } else {
    $this->output->set_status_header(404);
    }
    return;
    }

    $this->output->set_status_header($http_code);

    // If the format method exists, call and return the output in that format
    if(method_exists($this, ‘_format_’.$this->_format))
    {
    // Set the correct format header
    $this->output->set_header(‘Content-type: ‘.$this->_supported_formats[$this->_format]);

    $formatted_data = $this->{‘_format_’.$this->_format}($data);
    $this->output->set_output( $formatted_data );
    }

    // Format not supported, output directly
    else
    {
    $this->output->set_output( $data );
    }
    }

    -Chris.

  • jesse

    If you want some api’s authenticated and some not.

    in config/rest.php

    $config['basic_auth'] = array(‘your request uri’);

    in libraries/REST_Controller.php

    function __construct()
    {
    parent::Controller();

    $this->url = $this->_get_url();

    // How is this request being made? POST, DELETE, GET, PUT?
    $this->_method = $this->_detect_method();

    // Lets grab the config and get ready to party
    $this->load->config(‘rest’);

    if($this->config->item(‘rest_auth’) == ‘basic’ || in_array( $this->url,$this->config->item(‘basic_auth’)) )
    {
    $this->_prepare_basic_auth();
    }

    elseif($this->config->item(‘rest_auth’) == ‘digest’|| in_array( $this->url,$this->config->item(‘digest_auth’)) )
    {
    $this->_prepare_digest_auth();
    }

    switch($this->_method)
    {
    case ‘put’:
    // Set up out PUT variables
    parse_str(file_get_contents(‘php://input’), $this->_put_args);
    break;

    case ‘delete’:
    // Set up out PUT variables
    parse_str(file_get_contents(‘php://input’), $this->_delete_args);
    break;
    }

    // Set up our GET variables
    $this->_get_args = $this->uri->ruri_to_assoc();

    // Merge both for one mega-args variable
    $this->_args = array_merge($this->_get_args, $this->_put_args, $this->_delete_args);

    // Which format should the data be returned in?
    $this->_format = $this->_detect_format();
    }

    /// some where in the class put the function below.

    private function _get_url(){

    return $this->input->server(‘REQUEST_URI’);
    }

    // THIS WAS A FIVE MINUTE THING SO BE SURE THAT IS GOOD FOR YOU.

  • jesse

    could you remove my post it is not complete I will post the complete solution soon.

  • jesse

    this was missing

    private function _force_login($nonce = ”)
    {
    header(‘HTTP/1.0 401 Unauthorized’);
    header(‘HTTP/1.1 401 Unauthorized’);

    if( $this->config->item(‘rest_auth’) == ‘basic’ || in_array( $this->url,$this->config->item(‘basic_auth’) ) )
    {
    header(‘WWW-Authenticate: Basic realm=”‘.$this->config->item(‘rest_realm’).’”‘);
    }

    elseif($this->config->item(‘rest_auth’) == ‘digest’|| in_array( $this->url,$this->config->item(‘digest_auth’) ) )
    {
    header(‘WWW-Authenticate: Digest realm=”‘.$this->config->item(‘rest_realm’). ‘” qop=”auth” nonce=”‘.$nonce.’” opaque=”‘.md5($this->config->item(‘rest_realm’)).’”‘);
    }

    echo ‘Text to send if user hits Cancel button’;
    die();
    }

  • http://bruno-amaral.com Bruno Amaral

    Great job with this implementation! It was very helpful to me.

    However, I have an issue while exporting information in XML in portuguese. Characters such “ã” or “ú” are converted by htmlentities to HTML entities not supported by XML.

    I fix it by using htmlspecialchars instead of htmlentities.

  • http://www.johnryding.com John Ryding

    Hi Phil,

    Great write up on how to integrate RESTful services in one’s CI app, I plan on using your work. I have one bit of feedback for the article. PUT is actually integral to REST in that PUT requests are used to modify a resource, while POST is used to solely create resources. For example, i would make a PUT request to extend the expiration date of an invitation i sent out to access my website.

    Thanks again for taking the time to put this together!

  • djole
  • http://aivan.monceller.com aivan

    Hi Phil,

    are you using this for PyroCMS?

  • Jeff

    Images aren’t loading… Someone delete or move a folder? Can we get them back?

  • jeff

    Is there a client library which would allow scripts running on other sites to POST information securely to my API but which are not using CodeIgniter? For example, I’m creating an API that allows other websites to place orders on my site. They would POST information like their storefront id, their custom product and the price being sold. The API would then return the orderid number and other details.

    How could I have a site POST to my API without using the CodeIgniter library?

    Thanks so much!

  • Jeff

    Oh, and I’d like to avoid PEAR or any other libraries so that it can be as universal as possible (or package it with it)

  • ajax

    I just want to point out that this library plays well with HMVC hierarchical plug-in for Codeigniter.

    I tried making the rest controller into a separate module and succeeded without having to add any code.

    Hats off to the Author. Thank you Phil and keep up the great work !

  • Mark Allen

    Thanks Phil. I’ve stumbled across your website before. Thanks for all the great work.

  • http://joomla-jquery-internet.de Robbz

    Basic-Auth is not working with the twitter-api anymore since september 2010, because they switched to OAuth.

  • http://www.metalcat.net Jeremy Hutchings

    Nice, thanks for this !

  • Ben

    Hello,

    In CI I’m able to get rid of “index.php” by way of:
    $config['index_page'] = “”;

    But when I access http://localhost:8888/foobar/api/example/users/, I don’t get the xml for my users.

    Any help is much appreciated.

    Regards,
    Ben

  • http://www.gamaondev.com Rodrigo Gama

    Isn’t this approach gonna turn the REST Controller into a bottleneck of the whole system? I’m thinking about using CI and this lib for a project, but am really worried by that.

    Regards

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      In what way? This is just done per request. Everything runs through CodeIgniter’s Base and their normal controller, but this just adds a few extra rest-related checks.

      Doing more stuff always uses more memory, but this is not much more “stuff” to be doing. If you can think of any performance tweaks please let me know!

  • Adrian

    I am using a somewhat older server.
    Is there a minimum version level of CI and PHP required to use this wonderful tool?

    Regards
    Adrian

  • madrico

    This is awesome, but is there a friendly-url fix or work around? I’d like to keep the purity of friendly-urls and to have things restful, if that makes sense.

    thanks in advance!!

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      Not sure what you mean about friendly URL’s, it couldn’t get any friendlier!

      If you’re talking about formats you can use .json if you like.

  • Rosandra Cuello

    This tutorial is great. Thank you!

  • http://www.incisivepoint.com Jack Starr

    Very useful stuff, as CI developer i will need this..

    Thanks a lot Phil.

  • http://www.nusacode.com Juanra

    Hi Phil,

    Amazing tutorial, thank you so much for it. I’m using your lib and when i try to use cvs or html format i getting this error:

    A PHP Error was encountered

    Severity: Warning

    Message: array_keys() [function.array-keys]: The first argument should be an array

    Filename: libraries/REST_Controller.php

    Line Number: 790

    I check it quickly and I think you are sending just the first row of the $data array to the array_keys function.

    // Format HTML for output
    private function _format_csv($data = array())
    {
    // Multi-dimentional array
    if (isset($data[0]))
    {
    $headings = array_keys($data[0]);
    }

    // Single array
    else
    {
    $headings = array_keys($data);
    $data = array($data);
    }

    $output = implode(‘,’, $headings).”\r\n”;
    foreach($data as &$row)
    {
    $output .= ‘”‘.implode(‘”,”‘,$row).”\”\r\n”;
    }

    return $output;
    }

    • http://dosocials.com Emiliano

      Thats probably because you’re sending teh rest_controller a $query->result(). Which means that you’re sending an object instead of an array.

      REST Controller expects (it seems at least) always arrays, not objects :), you can change $query->result() for $query->result_array()

      cheers!

  • http://swelldesigns.co.uk Simon

    Awesome, clear, helpful tutorial! Thank you and well done. Can’t wait to put this into practice.

  • Tom

    Has anyone managed to get this working when inputting a URL? I’m having a tonne of trouble with it. I’ve posted the issue up on StackOverflow: http://stackoverflow.com/questions/4408125/allowencodedslashes-issue

  • Steve

    I believe the link to Matchbox is actually called Incendiary:

    https://code.google.com/p/incendiary/

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      Nope, neither exist anymore. Use Modular Extensions instead.

  • http://codefight.org/ Damu

    Great tut phil.

    congrats for making in the CodeIgniter Reactor team.

  • Jonas

    Great tutorial, just one quick hint – you need to add security to the autoloaded libraries ($autoload['libraries'] = array(‘security’, etc.); in order to use the REST library…

    Thanks for the tut, Phil!

  • http://www.mnemonicdictionary.com/word/tawdry Amit Aggarwal

    Hi Phil,

    Thank a lot again for the awesome work.

    Just a small question : How can we upload some image files from rest client to rest server ?

    - Amit

  • Enrique

    Hi Phil
    I’ve downloaded your latest CodeIgniter RESTServer from GitHub, configured the base_url, and then tried to test it.
    I noticed the urls and folders have changed from the ones in the tutorial, but I saw the code and tried this url

    http://localhost/regcivil/restserver/index.php/api/example/user_get/id/1

    But I keep getting this: 0Unknown method.

    http://i.imgur.com/1Cd72.jpg

    How could I solve this? Thanks

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      Remove the _get from the method, that is implied for you as the HTTP request is a GET one (you’re loading it in your browser).

      The reason you see “0Unknown Method” is because the default return type is XML and the browser doesn’t know how to interpret it.

  • Regis

    Cannot get it to work at all. Using it in Mamp on a mac and getting a 500 server error. Tried it on a live hosted environment (MT), in a subdomain, like, http://dev.mydomain.com/restserver/ and I am getting the same 500 error… any, ideas? on mamp, php is 5.3.2. By the way, installed a simple CI (1.7.3) and it works well. Thank you for your help.

  • cn1109

    Regis

    I’m getting the same issues.
    Where the files modified?

    Can someone upload a working version or test the latest one?

    Thanks.

  • sridhar

    How to use API Keys?

    How to generate api keys?

    How to pass api-keys while accessing the api?

    Please help me…!

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      sridhar: API keys were a feature added in fairly recently under request from a client. Look at the keys.php example controller to see how it works.

      Then send a HTTP Header of X-API-KEY (or whatever matches in your rest.php config) and it’ll look up the keys table to see if it matches.

      Regis: My REST_Controller does not send a 500 error unless you tell it to, so its more likely an issue with your setup, mod_rewrite, virtual host, etc.

  • http://mammadipino.com Luciana

    Hi
    Thanks for the post. Lots of useful references. I’m familiar with the javascript jquery/ajax, so I would like to use that to integrate with the Restful API. I am learning codeigniter for now. I created an API based on your code above, but when I use the javascript ajax to consume it, the success data returned is null via JS. I can see the results from the API on the browser, but ajax still says the data variable is null. What am I missing? Thanks

  • Murk

    Having trouble getting the demo running. I have Wamp (Apache v2.2.17, PHP v5.3.5) on Vista (actually, looking above I don’t see any hints that anyone else is using a flavour of Doze, so I wonder whether that’s my problem right there) and have installed the demo files into a folder called “ci” in the web root. I have edited the config as suggested (base_url is set to http://localhost/ci/) but when I browse to localhost/ci I get a fatal error: Class ‘Controller’ not found in www\ci\application\controllers\welcome.php on line 3.

    When this didn’t work I tried installing/configuring the latest CodeIgniter build (2.0.0), which seemed to work fine on its own. A bit of Googling suggests that in later versions of CodeIgniter, the Controller class has been renamed to CI_Controller. I wondered if the demo had been written for an earlier version that had somehow gotten mixed up with a later version of CodeIgniter… Tried editing welcome.php and changing the class name, but it seems it can’t find this class either.
    I also found something about making sure that the system path in index.php was correct – checked that, and it seems to be OK. I haven’t renamed any files or folders within the structure, so I’m at a bit of a loss.

    Got another machine here running Ubuntu – I’m going to see whether it’ll run on there.

    Any hints? Anyone else having similar issues? Any other Windows users here, with or without similar problems?

    • Murk

      Also fails on Ubuntu, although this time I get no error message – just a blank white screen.

    • Murk

      Problem seems to have been solved by a colleague… looks like I was half way there! We changed two things:

      1) changed class def to “extends CI_Controller”

      2) changed constructor to call “parent::__construct();”

      Didn’t spot #2 because I haven’t done much work with classes in PHP, and wasn’t aware of this difference between PHP versions.

      Hope someone finds this useful!

      • http://philsturgeon.co.uk/ Phil Sturgeon
        Author

        Obviously if you use this with CodeIgniter 2.0 things will be different, that is why it’s bundled with 1.7.x. I assume people will use common sense while using this code…

  • http://noisykid.com/ Steve

    Would love to see an update to this for CI 2.0 – Should be pretty straight-forward. If I had the time I’d tackle it, hopefully some generous person will.

    • http://philsturgeon.co.uk/ Phil Sturgeon
      Author

      See the comments above. Not that much changed.

  • Darrin

    Thanks Murk – worked a treat for me.

  • Riddick

    I don’t understand how can I get error code with Rest client or I must append it to response?

  • http://www.theroadtosiliconvalley.com/ Ernest Semerda

    This is awesome, thanks for sharing.

    How would you implement caching around this if calls to DB need to be done to get the data?

  • http://alangalan.com Alan Garcia

    Great work! Thanks for contributing :)

    One issue: I’m getting a PHP Parse error on libraries/Format.php: syntax error, unexpected T_STATIC in on line 71.

    Us this a known issue, and if so, please recommend a fix? Thanks!

  • Sohel

    Hi,
    How I will check username and password against database?

    Regards,
    Sohel

  • jon

    Hi

    Many thanks for this article.

    Do I need to use a single controller class for the whole API?

    For example, I might want the following URLs.

    http://myapp/api/users (or perhaps even just http://myapp/users)
    http://myapp/api/customers
    http://myapp/api/products

    Would I need a single API Controller class to obtain this pattern of URLs? If I want to have different controller classes for each entity type, how could this be achieved.

    I’m new to CI so I might be missing something basic.

    all the best

    Jon

    • Sohel

      Hi Jon,
      You can create different controller classes according to your need. Just need to inherit the REST_Controller class as shown in the example.

  • http://onesandzeros.posterous.com Sofia

    I came here looking for a way to implement in CI restful output url’s like rails does, eg. posts/index.json, posts/index.xml, posts/index.html to return a list of posts in json, xml, or regular html format. So if anyone’s looking for the same thing i posted a simple way to implement that in this gist https://gist.github.com/969648 (main code in welcome.php & routes.php). After that it’s just a switch statement on the format.

    Cheers

  • Tzafrir

    All work fine, except the digest authentication (I can work with basic authentication, but when I set the config to digest authentication I fail to authenticate)