1. Code
  2. PHP
  3. CodeIgniter

Trabajando con servicios RESTful en CodeIgniter

Como saben bien CodeIgniter esta llegando ha ser bien conocido por el poder que tiene PHP web framework de desarrollo, pero no es frecuente que veamos ejemplos de siendo usado para otra cosa. Hoy nosotros aprenderemos como podemos usar CodeIgniter para crear un API RESTful para tu aplicación existente, y demostrar como relacionar con tu propio API o otro servicio web RESTful, tal como Facebook y Twitter. Detalles del tutorial
Scroll to top

Spanish (Español) translation by James Kolce (you can also view the original English article)

Como saben bien CodeIgniter esta llegando ha ser bien conocido por el poder que tiene PHP web framework de desarrollo, pero no es frecuente que veamos ejemplos de siendo usado para otra cosa.  Hoy nosotros aprenderemos como podemos usar CodeIgniter para crear un API RESTful para tu aplicación existente, y demostrar como relacionar con tu propio API o otro servicio web RESTful, tal como Facebook y Twitter. 

Detalles del tutorial

Introducción

Si has estado siguiendo la serie CodeIgniter Desde Cero sabrás que es relativamente rápido y fácil ensamblar aplicaciones web simples tales como blogs, sistemas de administración de contenido, sitios de folleto, etc. Una cosa que probablemente no habías pensado es usar CodeIgniter para crear una API interactiva. Luego de probar varias implementaciones REST existentes, encontré que no solo tienen una falta de simplicidad pero que les faltaban la mayoría de características que esperarías de una implementación RESTful; así que construí una propia. Este tutorial te mostrará como usar este código para poner en marcha tu API REST, y da ejemplo de cómo intelectual con ella desde tu aplicación web.

Suposiciones

  1. Tienes un servidor web instalado localmente o en linea y sabes cómo administrar archivos en él.
  2. Has leído algunos de los tutoriales de CodeIgniter desde Cero.
  3. Sabes cómo instalar CodeIgniter.
  4. Sabes un poco sobre servicios RESTful.

Este tutorial está dividido en dos partes. Vamos a comenzar aprendiendo cómo crear un servicio RESTful, luego mas adelante aprenderemos como intelectual con él en algunas formas diferentes.

Parte 1—Creando una API RESTful

Paso 1: Instalando la Demo

Primeramente necesitarás descargar el código codeigniter-restserver de Github, extraerlo y mover el código a tu servidor.

Cuando abres la carpeta, verás una instalación completa la cuál está ahí para hacer mover la demo. Esto permite a la gente tener un juego con la demo REST antes de integrarla con tu aplicación existente.

Abre "application/config/config.php" y ajusta la base_url para tener enlaces funcionando. Esta base_url será diente para cada uno y depende completamente de donde subiste tus archivos.

Paso 2: Las URL

Con los archivos extraídos y la base_url ajustada, estamos listos para cargar nuestra instalación RESTful CodeIgniter y echar un vistazo a la demo proveída. Navega la URL base, que por defecto es:

http://localhost/restserver

Aquí vas a encontrar algunos enlaces de ejemplo al controlador example_api el cual puede ser encontrado en "application/controllers/example_api.php". Vamos a diseccionar las URL de estos ejemplos para ver lo que está ocurriendo. La primera URL es una muy simple.

Esta URL se ve como cualquier otra URL de CodeIgniter con un controlador y un método, pero te darás cuenta en este diagrama que el método es nombrado un "Resource". REST es sobre Resources y son esencialmente un sustantivo dentro de tu aplicación, con los cuales son interactuados (es decir, agregados, borrados, editados, consultados) basado en cabeceras HTTP y en cadenas de solicitud en la URL o argumentos HTTP.

El formato predeterminado de salida es XML, el cual es el que vemos en este ejemplo básico. Los otros enlaces son un poco mas largos y demuestran cómo pasar parámetros y mostrar cómo el formato de salida puede ser modificado en la URL:

Normalmente en CodeIgniter, simplemente pasas los valores de parámetros, pero un controlador REST acepta cualquier numero de parámetros en cualquier orden. Para que esto funcione, necesitamos pasar el nombre del parámetro seguido por el valor en pares.

Al final en la URL está el parámetro "format". Este es un parámetro reservado que va a modificar el formato de salida de los datos solicitados de la siguiente forma:

Dandole al desarrollador de API y la aplicación cliente la elección del formato de datos a usar, la API es abierta a una audiencia mucho mas amplia y puede ser usado con más lenguajes de programación y sistemas. Estos tres no son los únicos formatos soportados, desde el inicio tu API REST puede usar:

  • xml - casi cualquier lenguaje de programación puede leer xml
  • json - útil para JavaScript e incrementalmente en aplicaciones PHP.
  • csv - se abre con programas de hojas de cálculo
  • html - una tabla simple de HTML
  • php - Representación de código PHP que puede ser eval()'uado
  • serialize - Datos serializados que pueden ser deserializados en PHP

Mientras que agregar el formato a la URL no es técnicamente la forma más RESTful de cambiar formatos, permite hacer pruebas fácilmente en el navegador y deja a los desarrolladores sin cURL ejecutar simples solicitudes GET en la API. La forma más RESTful es enviar una cabecera Content-type al controlador REST usando cURL, pero eso será explicado después.

Paso 3: El Código

Ahora sí abres application/controllers/example_api.php inmediatamente notarás algunas diferencias de los controladores normales de CodeIgniter

REST_Controller

En el patrón MVC, un controlador es el punto central de la lógica. Es llamado cuando un usuario hace una solicitud y entonces basado en la lógica en el controlador recupera la información y muestra vistas. CodeIgniter contiene su propia lógica sobre cómo un Controlador debería de funcionar pero como estamos haciendo algo diferente necesitamos nuestra propia biblioteca REST_Controller para contener su propia lógica REST. Entonces en lugar de simplemente usar:

1
<?php
2
class Example_api extends Controller {
3
4
}

… necesitarás usar:

1
<?php
2
require(APPPATH'.libraries/REST_Controller.php');
3
4
class Example_api extends REST_Controller {
5
6
}

Trabajando con Recursos

Ahora tu control vacío está instalado, enseguida están los métodos o "recursos". Esto es posiblemente la parte más confusa del tutorial si estás acostumbrado a como CodeIgniter funciona. Basicamente, tomas los Recursos, el verbo HTTP y los combinas para hacer un nombre de método. Entonces los dos ejemplo que vimos antes tenían un Recurso user y users. Porque ambos fueron cargados en el navegador, sabemos que fue usando una solicitud GET y entonces los dos abajo son usados:

1
<?php
2
require(APPPATH'.libraries/REST_Controller.php');
3
4
class Example_api extends REST_Controller {
5
6
    function user_get()
7
    {
8
  	// respond with information about a user

9
    }
10
    
11
    function users_get()
12
    {
13
		// respond with information about several users

14
    }
15
}

Esto podría verse un poco extraño, pero te da la habilidad de usar la misma URL y responder a la solicitud dependiendo del verbo HTTP que ha sido usado. Si alguien intenta accesar a tu API en una forma que no está permitida (en este ejemplo PUT o DELETE) simplemente responderá con un 404. Si no estás seguro sobre verbos HTTP, déjame explicar.

GET

Usado para recuperar información sobre un recurso existente. Esto es usado por navegadores cuando ingresas una URL y presionas ir, o cuando haces clic en un enlace, así que es perfecto para recuperar información en uno de tus recursos REST (como user).

POST

Usado para actualizar un recurso existente con información. Los navegadores usan esto para enviar la mayoría de formularios en Internet, aunque algunos usan GET también enviando el formulario con una query string que contenga los datos de los campos.

PUT

Menos comúnmente usado y no soportado por la mayoría de navegadores, PUT es usado para crear un nuevo recurso.

DELETE

Tampoco es usado por muchos navegadores, este verbo HTTP es obviamente usado para borrar un recurso.

Si ponemos eso en código y permitimos cada verbo en el recurso user se vería como esto:

1
<?php
2
require(APPPATH'.libraries/REST_Controller.php');
3
4
class Example_api extends REST_Controller {
5
6
    function user_get()
7
    {
8
		// respond with information about a user

9
    }
10
11
    function user_put()
12
    {
13
		// create a new user and respond with a status/errors

14
    }
15
16
    function user_post()
17
    {
18
		// update an existing user and respond with a status/errors

19
    }
20
21
    function user_delete()
22
    {
23
		// delete a user and respond with a status/errors

24
    }
25
}

Accediendo a parámetros y devolviendo datos

Ahora se le ha dado a la API su estructura ajustando los recursos y definiendo un método para cada verbo HTTP que deseemos soportar; necesitamos parámetros así podemos usar nuestros modelos y bibliotecas de CodeIgniter. Este es uno de los mayores beneficios de usar CodeIgniter para nuestra API, podemos usar nuestros modelos y bibliotecas existentes y no tener que re-codificarlos.

1
<?php
2
require(APPPATH'.libraries/REST_Controller.php');
3
4
class Example_api extends REST_Controller {
5
6
    function user_get()
7
    {
8
		$data = array('returned: '. $this->get('id'));
9
		$this->response($data);
10
    }
11
    
12
    function user_post()
13
    {		
14
		$data = array('returned: '. $this->post('id'));
15
		$this->response($data);
16
    }
17
18
    function user_put()
19
    {		
20
		$data = array('returned: '. $this->put('id'));
21
		$this->response($data;
22
    }
23
24
    function user_delete()
25
    {
26
		$data = array('returned: '. $this->delete('id'));
27
		$this->response($data);
28
    }
29
}

Este ejemplo contiene cinco nuevas piezas de código:

$this->get()

Es usado para devolver variables GET de ya sea una query string como esta index.php/example_api/user?id=1 o puede ser ajustado en la forma mas CodeIgnitera con index.php/example_api/user/id/1

$this->post()

Es un alias para $this->input->post() el cual es el método de CodeIgniter para accesar variables $_POST con protección XSS.

$this->put()

Lee argumentos PUT en cabeceras HTTP o via cURL.

$this->delete()

Como lo habrás supuesto, esto lee argumentos DELETE, también en cabeceras HTTP o via cURL.

$this->response()

Envía datos al navegador en cualquier formato de datos que se haya solicitado, o predetermina a XML. Puedes opcionalmente pasar un código de estado HTTP para mostrar que ha funcionado o ha fallado. Por ejemplo, si el ID proveído no estaba en la base de datos, podrías usar $this->response(array('error' => 'User not found.'), 404);

Paso 4: Trabajando con tus Modelos

Hasta ahora, hemos estado trabajando con una API de ejemplo en una instalación limpia. El siguiente paso es conseguir una API REST corriendo de tu base de código existente.

Aunque la descarga viene con una instalación de CodeIgniter completa para la demo y para permitir que la API sea construida desde cero, los únicos dos archivos de importancia son:

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

Suelta esos dos archivos en tu aplicación CodeIgniter y crea un nuevo controlador API.

1
<?php
2
require(APPPATH.'/libraries/REST_Controller.php');
3
4
class Api extends REST_Controller
5
{
6
	function user_get()
7
    {
8
        if(!$this->get('id'))
9
        {
10
        	$this->response(NULL, 400);
11
        }
12
13
        $user = $this->user_model->get( $this->get('id') );
14
    	
15
        if($user)
16
        {
17
            $this->response($user, 200); // 200 being the HTTP response code

18
        }
19
20
        else
21
        {
22
            $this->response(NULL, 404);
23
        }
24
    }
25
    
26
    function user_post()
27
    {
28
        $result = $this->user_model->update( $this->post('id'), array(
29
        	'name' => $this->post('name'),
30
        	'email' => $this->post('email')
31
        ));
32
        
33
        if($result === FALSE)
34
        {
35
        	$this->response(array('status' => 'failed'));
36
        }
37
        
38
        else
39
        {
40
        	$this->response(array('status' => 'success'));
41
        }
42
        
43
    }
44
    
45
    function users_get()
46
    {
47
        $users = $this->user_model->get_all();
48
        
49
        if($users)
50
        {
51
            $this->response($users, 200);
52
        }
53
54
        else
55
        {
56
            $this->response(NULL, 404);
57
        }
58
    }
59
}
60
?>

Esto muestra una API de ejemplo con algunos nombres de modelo genéricos. En el primer método, estamos tomando un ?id=XX y pasándolo al modelo. Si son encontrados datos los enviamos a la función $this->response() con un estado 200. Si nada es encontrado, no se devuelve el body sino un 404 para decir que nada ha sido encontrado. Puedes imaginar como esto podría ser expandido para correr toda clase de actividades API en tu aplicación web.

Paso 5: Asegurando la API

Ahora que tu API está construida necesita asegurarse así solo usuarios con cierto nivel de acceso pueden interactuar con la API. Para ajustar el tipo de inicio de sesión, nombres de usuario y contraseñas abre "application/config/rest.php" dentro de tu base de código.

1
/*

2
|--------------------------------------------------------------------------

3
| REST Login

4
|--------------------------------------------------------------------------

5
|

6
| Is login required and if so, which type of login?

7
|

8
|	'' = no login required, 'basic' = relatively secure login, 'digest' = secure login

9
|

10
*/
11
$config['rest_auth'] = 'basic';

None

Cualquiera puede interactuar con cualquier controlador de tu API.

Basic

Un método de inicio de sesión relativamente inseguro el cual debería de ser usado en redes internas o seguras.

Digest

Un método mucho mas seguro que encripta nombres de usuario y contraseñas. Si deseas tener una API protegida a la cual cualquier pudiera acceder, usa digest.

1
/*

2
|--------------------------------------------------------------------------

3
| REST Login usernames

4
|--------------------------------------------------------------------------

5
|

6
| Array of usernames and passwords for login

7
|

8
|	array('admin' => '1234')

9
|

10
*/
11
$config['rest_valid_logins'] = array('admin' => '1234');

Ajustando los usuarios es simple. Cada inicio de sesión es un elemento en el array, con una clave y valor. La clave es el nombre de usuario y el valor es la contraseña. Agrega tantos como quieras a este array y envíalos a cualquiera que estará usando la API.

Parte 2 - Interactuando con Servicios RESTful

Ya sea la API que has construido un servicio publico tal como Twitter, querrás ser capaz de interactuar con el de alguna forma. Ver como funcionan los servicios RESTful con solicitudes HTTP básicas es fácil hacer esto en un número de formas diferentes.

Diferentes Métodos para Interactuar con REST

Cada uno de estos métodos diferentes de interacción serán mostrados con el código puesto directamente en los métodos del Controlador. Esto es puramente para que las demos sean mas fáciles de leer y normalmente serían puestos dentro de un modelo o una biblioteca para una correcta separación MVC.

file_get_contents()

Usando la simplísima función PHP file_get_contents(), puedes hacer una solicitud GET básica. Este es uno de los de los métodos mas básicos pero vale la pena mencionarlo para esos momentos "rápidos y sucios".

1
$user = json_decode(
2
	file_get_contents('http://example.com/index.php/api/user/id/1/format/json')
3
);
4
5
echo $user->name;

Vale la pena notar que, mientras este método no funcionará usando autenticación Digest de HTTP, si estás usando autenticación básica HTTP puedes usar la siguiente sintaxis para conseguir datos de tu API RESTful protegida por contraseña:

1
$user = json_decode(
2
	file_get_contents('http://admin:1234@example.com/index.php/api/user/id/1/format/json')
3
);
4
5
echo $user->name;

Hay algunos problemas con el uso de este método: la única forma de ajustar cabeceras HTTP extras es ajustarlas manualmente usando la función stream_context_create() de PHP, la cuál puede ser muy complicada para desarrolladores que son nuevos a los mecanismos internos de solicitudes HTTP. Otra desventaja es que solo recibes el cuerpo de la respuesta HTTP en su formato crudo, lo cual significa que necesitarás manejar la conversión de cada solicitud.

cURL

cURL es la forma mas flexible de interactuar con una API REST ya que fue diseñador para exactamente este tipo de cosas. Puedes ajustar cabeceras HTTP, parámetros HTTP y mucho mas. Aquí está un ejemplo de cómo actualizar un usuario con nuestro example_api y cURL para hacer una solicitud POST:

1
    function native_curl($new_name, $new_email)
2
    {
3
	    $username = 'admin';
4
		$password = '1234';
5
		
6
		// Alternative JSON version

7
		// $url = 'http://twitter.com/statuses/update.json';

8
		// Set up and execute the curl process

9
		$curl_handle = curl_init();
10
		curl_setopt($curl_handle, CURLOPT_URL, 'http://localhost/restserver/index.php/example_api/user/id/1/format/json');
11
		curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
12
		curl_setopt($curl_handle, CURLOPT_POST, 1);
13
		curl_setopt($curl_handle, CURLOPT_POSTFIELDS, array(
14
			'name' => $new_name,
15
			'email' => $new_email
16
		));
17
		
18
		// Optional, delete this line if your API is open

19
		curl_setopt($curl_handle, CURLOPT_USERPWD, $username . ':' . $password);
20
		
21
		$buffer = curl_exec($curl_handle);
22
		curl_close($curl_handle);
23
		
24
		$result = json_decode($buffer);
25
26
		if(isset($result->status) && $result->status == 'success')
27
		{
28
			echo 'User has been updated.';
29
		}
30
		
31
		else
32
		{
33
			echo 'Something has gone wrong';
34
		}
35
    }

La interacción con tu API de esta forma funciona bien, pero hay dos problemas con este método:

  1. Usa una fea y confusa sintaxis - imagina crear varias aplicaciones basado en eso.
  2. cURL no está instalado en todos los servidores de forma predeterminada.

Para resolver esta sintaxis fea, una biblioteca para cURL ha sido desarrollada para CodeIgniter la cual simplifica cosas inmensamente.

Exactamente la misma solicitud hecha con la biblioteca cURL se vería como esto:

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

11
		$this->curl->http_login($username, $password);
12
13
		$this->curl->post(array(
14
			'name' => $new_name,
15
			'email' => $new_email
16
		));
17
		
18
		$result = json_decode($this->curl->execute());
19
20
		if(isset($result->status) && $result->status == 'success')
21
		{
22
			echo 'User has been updated.';
23
		}
24
		
25
		else
26
		{
27
			echo 'Something has gone wrong';
28
		}
29
    }

Mucho mejor a la visa, ¿cierto? Bueno, hay un método incluso mas fácil para trabajar con REST en tus aplicaciones CodeIgniter.

REST client library

Una REST client library ha sido desarrollada que se posiciona por encima es esta librería cURL la cual maneja la conversión de formato, inicios de sesión HTTP y otros varios aspectos en tu API REST.

1
    function rest_client_example($id)
2
    {
3
		$this->load->library('rest', array(
4
			'server' => 'http://localhost/restserver/index.php/example_api/',
5
			'http_user' => 'admin',
6
			'http_pass' => '1234',
7
			'http_auth' => 'basic' // or 'digest'

8
		));
9
		
10
        $user = $this->rest->get('user', array('id' => $id), 'json');
11
        
12
        echo $user->name;
13
    }

Aquí puedes ver que estamos haciendo una solicitud GET, enviando id como parámetro y diciendo a la biblioteca que queremos 'json' como formato de contenido. Esto maneja el ajuste de Content-type por ti, y convierte los datos en un objeto PHP para ti. Puedes cambiar este valor a 'xml', 'json', 'serialize', 'php', 'csv' o cualquier MIME-type que quieras, por ejemplo:

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

Como probablemente habrás supuesto también como $this->rest->get(), la librería también soporta $this->rest->post(), $this->rest->put(), $this-<rest->delete() para igualar todos tus métodos REST_Controller.

Necesitarás hacer var_dump() a los resultados viniendo del REST client library para asegurarte de que estás consiguiendo el formato de datos correcto. La conversión algunas veces será un array y algunas veces un objeto dependiendo de como sea convertido por PHP. Si el MIME-type devuelto no es soportado entonces simplemente devolverá el formato como texto plano.

Hablando a Twitter

Usando esta biblioteca REST puedes hablar a otros servicios RESTful tales como Twitter y Facebook. Aquí está un ejemplo simple de como puedes conseguir detalles de un usuario en específico basado en su ID, usado el formato predeterminado de Twitter XML.

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

Viendo a esto, te darás cuenta de que interactuar con una API de Twitter es un poco diferente en algunas formas.

  1. Soportan cambio de formato basado en URL de la forma .json en lugar de /format/json. Algunos requieren una extensión, algunos no; así que siempre es mejor agregarlos.
  2. Mayormente solo soportan GET/POST, pero están comenzando a agregar mas métodos DELETE.
  3. No siempre tienen solo un recurso en su URL, por ejemplo: users/search es un método REST, pero lists es otro.

Mantén un ojo en esas diferencias ya que pueden atraparte. Si te atoras, simplemente has echo $this->rest->debug() para un completo rango de información sobre tu solicitud REST.

Resumen

Combinando lo que sabes sobre servicios RESTful, la REST client library de CodeIgniter y la documentación para la API de Twitter - o cualquier otra documentación API RESTful para ese asunto - puedes crear unas aplicaciones bastante poderosas que integren con cualquier servicio publico web o personalizado usando REST. Puedes extender tu API creando mas REST_Controller e incluso hacer una API modular usando Matchbox o Separación Modular para crear un controlador api.php para cada modulo para ayudarte a mantener tu API pie organizada como tu aplicación.

Escribe un Tutorial Plus

¿Sabías que puedes ganar hasta $600 escribiendo un tutorial o un video PLUS para nosotros? Estamos buscando tutoriales en profundidad y bien escritos sobre HTML, CSS, PHP y JavaScript. Si tienes la habilidad, por favor contacta a Jeffrey a nettuts@tutsplus.com.

Por favor date cuenta de que la compensación será dependiente de la calidad final del tutorial y del video.

Write a PLUS tutorial