1. Code
  2. PHP

Crear una aplicación web centrada en API

Scroll to top
19 min read

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

¿Estás planeando comenzar a trabajar en una nueva aplicación web? En este tutorial, discutiremos cómo crear una aplicación web centrada en API y explicaremos por qué esto es esencial en el mundo multiplataforma actual.

Introducción

¿API?

Para aquellos que no están familiarizados con el término, API es la abreviatura de Application Programming Interface. De acuerdo con Wikipedia:

Una interfaz de programación de aplicaciones (API) es una especificación basada en el código fuente que los componentes de software deben usar como interfaz para comunicarse entre ellos. Una API puede incluir especificaciones para rutinas, estructuras de datos, clases de objetos y variables.

API VisualizationAPI VisualizationAPI Visualization

Visualización de una API

Cortesía de http://blog.zoho.com

En términos más simples, una API se refiere a un conjunto de funciones integradas en una aplicación, que pueden ser utilizadas por otras aplicaciones (o por sí mismas, como veremos más adelante) para interactuar con la aplicación. Una API es una excelente manera de exponer la funcionalidad de una aplicación a aplicaciones externas de forma segura, ya que todas las funciones que estas aplicaciones externas pueden hacer están limitadas por la funcionalidad expuesta en la API.

¿Qué es una aplicación web "centrada en la API"?

Una aplicación web centrada en API es una aplicación web que básicamente ejecuta la mayoría, si no, toda su funcionalidad a través de llamadas API.

Una aplicación web centrada en API es una aplicación web que básicamente ejecuta la mayoría, si no, toda su funcionalidad a través de llamadas API. Por ejemplo, si vas a iniciar sesión en un usuario, debes enviar tus credenciales a la API, y la API te devolverá un resultado que indica si el usuario proporcionó la combinación correcta de usuario-contraseña.

Otra característica de una aplicación web centrada en API es que la API siempre será sin estado, lo que significa que no puede reconocer llamadas de API por sesión. Dado que las llamadas a la API se realizarán generalmente a través del código de servidor, será difícil implementar el manejo de la sesión, ya que generalmente no hay cookies involucradas en eso. Esta limitación es realmente buena: esto "obliga" a un desarrollador a crear una API que no funciona en función del estado del usuario actual, sino más bien de la funcionalidad, lo que a su vez facilita la prueba, ya que el estado actual de un usuario no necesita ser recreado

¿Por qué pasar todo este problema?

Como desarrolladores web, hemos visto evolucionar la tecnología de primera mano. Es de conocimiento común que las personas de hoy no solo usan aplicaciones a través de un navegador, sino a través de otros dispositivos, como teléfonos móviles y tabletas. Por ejemplo, este artículo en Mashable, titulado "Los consumidores ahora gastan más tiempo en aplicaciones móviles que la Web", afirma:

Los consumidores están pasando más tiempo en aplicaciones móviles que en la web por primera vez, según un nuevo informe.

Flurry comparó sus datos móviles con las estadísticas de comScore y Alexa, y descubrió que, en junio, los consumidores pasaron 81 minutos al día usando aplicaciones móviles, en comparación con los 74 minutos de navegación en la web.

Aquí hay un artículo más reciente de ReadWriteWeb, titulado "Más personas navegan en dispositivos móviles que utilizan IE6 e IE7 combinados":

Los últimos datos sobre las tendencias de los navegadores de Sitepoint muestran que más personas navegan por la Web en teléfonos inteligentes que usan Internet Explorer 6 y 7 combinados. Esos dos viejos cacharros han sido las pesadillas de los desarrolladores web durante años, lo que exige que los sitios se degraden lo mejor posible al mínimo común denominador de los navegadores. Pero es un mundo nuevo ahora; 6.95% de la actividad web en noviembre de 2011 fue en navegadores móviles, y solo 6.49% fue en IE 6 o 7.

Como podemos ver claramente, cada vez más personas obtienen sus noticias de lugares alternativos, específicamente dispositivos móviles.

¿Qué tiene esto que ver conmigo al crear una aplicación web centrada en API?

Esto conduciría inevitablemente a un mayor uso de nuestra aplicación, ya que se puede usar en cualquier lugar que desee una persona.

Una de las principales ventajas de crear una aplicación centrada en API es que te ayuda a crear funcionalidades que pueden usar CUALQUIER dispositivo, ya sea un navegador, un teléfono móvil, una tableta o incluso una aplicación de escritorio. Todo lo que necesitas hacer es crear la API de tal manera que todos estos dispositivos se puedan comunicar con ella, y ¡listo! ¡Habrás creado una aplicación centralizada que puede tomar el input y ejecutar la funcionalidad desde cualquier dispositivo que tenga una persona!

API-Centric Application DiagramAPI-Centric Application DiagramAPI-Centric Application Diagram

Diagrama de una aplicación centrada en API

Al crear una aplicación de esta manera, podemos aprovechar fácilmente los diferentes medios utilizados por diferentes personas. Esto conduciría inevitablemente a un mayor uso de una aplicación, ya que puede utilizarse en cualquier lugar que desee una persona.

Para aclarar el punto, aquí hay un artículo sobre el nuevo sitio web rediseñado de Twitter, que nos dice cómo ahora usan su API para impulsar Twitter.com, esencialmente haciendo que se centre en una API:

Uno de los cambios arquitectónicos más importantes es que Twitter.com ahora es cliente de nuestra propia API. Obtiene datos de los mismos puntos finales que usa el sitio móvil, nuestras aplicaciones para iPhone, iPad, Android y todas las aplicaciones de terceros. Este cambio nos permitió asignar más recursos al equipo de API, generando más de 40 parches. En la carga de la página inicial y cada llamada del cliente, todos los datos ahora se extraen de un caché de fragmentos JSON altamente optimizado.

En este tutorial, crearemos una aplicación de lista TODO simple que sea API-Centric y crearemos un cliente de front-end en el navegador que interactúe con nuestra aplicación de listas TODO. Al final, conocerás las partes integrales de una aplicación centrada en la API y, al mismo tiempo, cómo facilitar la comunicación segura entre las dos. Con eso en mente, ¡comencemos!


Paso 1: Planificar las funciones de la aplicación

La aplicación TODO que construiremos en este tutorial tendrá las funciones CRUD básicas:

  • Crear elementos en el TODO 
  • Read, de "Leer" los elementos del TODO
  • Update, de "Actualizar" los elementos del TODO (renombrar, marcar como hecho, marcar como deshecho)
  • Delete, de "Eliminar" los elementos del TODO

Cada artículo TODO tendrá:

  • un título
  • Una fecha
  • una descripción
  • una bandera para indicar si se ha completado el elemento del TODO
  • Vamos a simular también la aplicación para que tengamos una guía sobre cómo se verá después:

    SimpleTODO MockupSimpleTODO MockupSimpleTODO Mockup

    Maquetado simple del TODO

    Paso 2: Crea el servidor API

    Dado que estamos desarrollando una aplicación centrada en API, crearemos dos "proyectos": el servidor API y el cliente front-end. Comencemos creando primero el servidor API.

    En la carpeta de tu servidor web, crea una carpeta llamada simpletodo_api, y crea un archivo index.php. Este archivo index.php actuará como un controlador frontal para la API, por lo que todas las solicitudes al servidor API se realizarán a través de este archivo. Ábrelo y pon el siguiente código dentro:

1
2
<?php
3
// Define path to data folder

4
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));
5
6
//include our models

7
include_once 'models/TodoItem.php';
8
9
//wrap the whole thing in a try-catch block to catch any wayward exceptions!

10
try {
11
  //get all of the parameters in the POST/GET request

12
	$params = $_REQUEST;
13
	
14
	//get the controller and format it correctly so the first

15
	//letter is always capitalized

16
	$controller = ucfirst(strtolower($params['controller']));
17
	
18
	//get the action and format it correctly so all the

19
	//letters are not capitalized, and append 'Action'

20
	$action = strtolower($params['action']).'Action';
21
22
	//check if the controller exists. if not, throw an exception

23
	if( file_exists("controllers/{$controller}.php") ) {
24
		include_once "controllers/{$controller}.php";
25
	} else {
26
		throw new Exception('Controller is invalid.');
27
	}
28
	
29
	//create a new instance of the controller, and pass

30
	//it the parameters from the request

31
	$controller = new $controller($params);
32
	
33
	//check if the action exists in the controller. if not, throw an exception.

34
	if( method_exists($controller, $action) === false ) {
35
		throw new Exception('Action is invalid.');
36
	}
37
	
38
	//execute the action

39
	$result['data'] = $controller->$action();
40
	$result['success'] = true;
41
	
42
} catch( Exception $e ) {
43
	//catch any exceptions and report the problem

44
	$result = array();
45
	$result['success'] = false;
46
	$result['errormsg'] = $e->getMessage();
47
}
48
49
//echo the result of the API call

50
echo json_encode($result);
51
exit();

Lo que esencialmente hemos construido aquí es un controlador frontal simple que hace lo siguiente:

  • Aceptar una llamada API con cualquier cantidad de parámetros
  • Extraer el Controller y el Action para la llamada API
  • Realizar las comprobaciones necesarias para asegurarse de que el Controller y el Action existen
  • Ejecutar la llamada a la API
  • Capturar errores, si hay alguno
  • Enviar un resultado a la persona que llama

Además del archivo index.php, crea tres carpetas: controllersmodels data 

API server folders
  • La carpeta controllers contendrá todos los controladores que usaremos para el servidor API. Lo construiremos utilizando la arquitectura MVC para que la estructura del servidor API esté más limpia y organizada.
  • La carpeta models contendrá todos los modelos de datos para el servidor API.
  • La carpeta data estará donde el servidor API guarda cualquier información

Dirígete a la carpeta controllers y crea un archivo llamado Todo.php. Este será nuestro controlador para cualquier tarea relacionada con la lista TODO. Con las funciones que necesitaremos para nuestra aplicación TODO en mente, crea los métodos necesarios para el controlador Todo:

1
2
3
<?php
4
class Todo
5
{
6
	private $_params;
7
	
8
	public function __construct($params)
9
	{
10
		$this->_params = $params;
11
	}
12
	
13
	public function createAction()
14
	{
15
		//create a new todo item

16
	}
17
	
18
	public function readAction()
19
	{
20
		//read all the todo items

21
	}
22
	
23
	public function updateAction()
24
	{
25
		//update a todo item

26
	}
27
	
28
	public function deleteAction()
29
	{
30
		//delete a todo item

31
	}
32
}

Ahora, agrega la funcionalidad necesaria a cada action. Proporcionaré el código para el método createAction y dejaré que crees el código para los otros métodos. Si no estás de humor, puedes descargar el código fuente de la demostración y copiarla desde allí.

1
2
3
public function createAction()
4
{
5
	//create a new todo item

6
	$todo = new TodoItem();
7
	$todo->title = $this->_params['title'];
8
	$todo->description = $this->_params['description'];
9
	$todo->due_date = $this->_params['due_date'];
10
	$todo->is_done = 'false';
11
	
12
	//pass the user's username and password to authenticate the user

13
	$todo->save($this->_params['username'], $this->_params['userpass']);
14
	
15
	//return the todo item in array format

16
	return $todo->toArray();
17
}

Crea un archivo llamado TodoItem.php dentro de la carpeta models para que podamos crear el código de "creación de elementos". Ten en cuenta que no me conectaré a una base de datos, sino que guardaré la información en archivos. Sin embargo, debería ser relativamente fácil hacer que esto funcione con cualquier base de datos.

1
2
3
<?php
4
class TodoItem
5
{
6
	public $todo_id;
7
	public $title;
8
	public $description;
9
	public $due_date;
10
	public $is_done;
11
	
12
	public function save($username, $userpass)
13
	{
14
		//get the username/password hash

15
		$userhash = sha1("{$username}_{$userpass}");
16
		if( is_dir(DATA_PATH."/{$userhash}") === false ) {
17
			mkdir(DATA_PATH."/{$userhash}");
18
		}
19
		
20
		//if the $todo_id isn't set yet, it means we need to create a new todo item

21
		if( is_null($this->todo_id) || !is_numeric($this->todo_id) ) {
22
			//the todo id is the current time

23
			$this->todo_id = time();
24
		}
25
		
26
		//get the array version of this todo item

27
		$todo_item_array = $this->toArray();
28
		
29
		//save the serialized array version into a file

30
		$success = file_put_contents(DATA_PATH."/{$userhash}/{$this->todo_id}.txt", serialize($todo_item_array));
31
		
32
		//if saving was not successful, throw an exception

33
		if( $success === false ) {
34
			throw new Exception('Failed to save todo item');
35
		}
36
		
37
		//return the array version

38
		return $todo_item_array;
39
	}
40
	
41
	public function toArray()
42
	{
43
		//return an array version of the todo item

44
		return array(
45
			'todo_id' => $this->todo_id,
46
			'title' => $this->title,
47
			'description' => $this->description,
48
			'due_date' => $this->due_date,
49
			'is_done' => $this->is_done
50
		);
51
	}
52
}

El método createAction llama a dos funciones en el modelo TodoItem:

  • save() - Esto guarda el TodoItem en un archivo, así como establece el todo_id para el TodoItem si es necesario
  • toArray () - Esto devuelve una versión de matriz de TodoItem, donde las variables son los índices de la matriz

Como se llama a la API a través de solicitudes HTTP, probemos esa llamada API llamándola a través del navegador:

http://localhost/simpletodo_api/?controller=todo&action=create&title=test%20title&description=test%20description&due_date=12/08/2011&username=nikko&userpass=test1234

Si todo funcionó, deberías ver una nueva carpeta dentro de la carpeta data, y dentro de esa carpeta, deberías ver un archivo con el siguiente contenido:

createAction() resultcreateAction() resultcreateAction() result

Resultado createAction()

¡Felicidades! ¡Creaste con éxito un servidor API y has realizado una llamada API!


Paso 3: Asegura el servidor API con un APP ID y un APP SECRET

Actualmente, el servidor API está configurado para aceptar TODAS las solicitudes API. Tendremos que limitarlo solo a nuestras propias aplicaciones, para garantizar que solo nuestros clientes front-end puedan realizar solicitudes API. Alternativamente, puedes crear un sistema en el que los usuarios puedan crear sus propias aplicaciones que tengan acceso a tu servidor API, de forma similar a cómo funcionan las aplicaciones de Facebook y Twitter.

Comienza creando un conjunto de pares de claves de id para los clientes que usarán el servidor API. Como esto es solo una demostración, podemos usar cualquier cadena aleatoria de 32 caracteres. Para la APP ID, digamos que es la aplicación APP001.

Abre el archivo index.php nuevamente y luego actualízalo con el siguiente código:

1
2
3
<?php
4
// Define path to data folder

5
define('DATA_PATH', realpath(dirname(__FILE__).'/data'));
6
7
//Define our id-key pairs

8
$applications = array(
9
	'APP001' => '28e336ac6c9423d946ba02d19c6a2632', //randomly generated app key 

10
);
11
//include our models

12
include_once 'models/TodoItem.php';
13
14
//wrap the whole thing in a try-catch block to catch any wayward exceptions!

15
try {
16
	//*UPDATED*

17
	//get the encrypted request

18
	$enc_request = $_REQUEST['enc_request'];
19
	
20
	//get the provided app id

21
	$app_id = $_REQUEST['app_id'];
22
	
23
	//check first if the app id exists in the list of applications

24
	if( !isset($applications[$app_id]) ) {
25
		throw new Exception('Application does not exist!');
26
	}
27
	
28
	//decrypt the request

29
	$params = json_decode(trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $applications[$app_id], base64_decode($enc_request), MCRYPT_MODE_ECB)));
30
	
31
	//check if the request is valid by checking if it's an array and looking for the controller and action

32
	if( $params == false || isset($params->controller) == false || isset($params->action) == false ) {
33
		throw new Exception('Request is not valid');
34
	}
35
	
36
	//cast it into an array

37
	$params = (array) $params;
38
	...
39
	...
40
	...

Lo que hemos hecho aquí es en realidad implementar una forma muy simple de autenticar a nuestros clientes front-end utilizando un sistema similar a la autenticación de clave pública-privada. Básicamente, aquí está el desglose paso a paso de cómo ocurre la autenticación:

Public-key encryptionPublic-key encryptionPublic-key encryption

Encriptación de clave pública
  • se realiza una llamada API, en ella se proporciona $app_id y $enc_request.
  • el valor de $enc_request son los parámetros de llamada API, cifrados mediante APP KEY. La APP KEY NUNCA se envía al servidor, solo se utiliza para actualizar la solicitud. Además, la solicitud solo se puede descifrar utilizando la APP KEY.
  • una vez que la llamada API llega al servidor de la API, se verificará su propia lista de aplicaciones para la APP ID proporcionada
  • cuando se encuentra, el servidor API intenta descifrar la solicitud utilizando la clave que coincide con la APP ID enviada
  • si fue exitoso para descifrarlo, entonces continúa con el programa

Ahora que el servidor API está protegido con una APP ID y una APP SECRET, podemos comenzar a programar un cliente de aplicaciones para el servidor API.


Paso 4: Crear el navegador cliente Front-end

Comenzaremos por configurar una nueva carpeta para el cliente front-end. Crea una carpeta llamada simpletodo_client_browser en la carpeta de tu servidor web. Cuando hayas terminado, crea un archivo index.php y coloca este código dentro:

1
2
3
<!DOCTYPE html>
4
<html>
5
<head>
6
	<title>SimpleTODO</title>
7
	
8
	<link rel="stylesheet" href="css/reset.css" type="text/css" />
9
	<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
10
	
11
	<script src="js/jquery.min.js"></script>
12
	<script src="js/jquery-ui-1.8.16.custom.min.js"></script>
13
	
14
	<style>
15
	body {
16
		padding-top: 40px;
17
	}
18
	#main {
19
		margin-top: 80px;
20
		text-align: center;
21
	}
22
	</style>
23
</head>
24
<body>
25
	<div class="topbar">
26
		<div class="fill">
27
			<div class="container">
28
				<a class="brand" href="index.php">SimpleTODO</a>
29
			</div>
30
		</div>
31
	</div>
32
	<div id="main" class="container">
33
		<form class="form-stacked" method="POST" action="login.php">
34
			<div class="row">
35
				<div class="span5 offset5">
36
					<label for="login_username">Username:</label>
37
					<input type="text" id="login_username" name="login_username" placeholder="username" />
38
				
39
					<label for="login_password">Password:</label>
40
					<input type="password" id="login_password" name="login_password" placeholder="password" />
41
					
42
				</div>
43
			</div>
44
			<div class="actions">
45
				<button type="submit" name="login_submit" class="btn primary large">Login or Register</button>
46
			</div>
47
		</form>
48
	</div>
49
</body>
50
</html>

Eso debería verse más o menos así:

SimpleTODO Login PageSimpleTODO Login PageSimpleTODO Login Page

Página de inicio de sesión del SimpleDODO

Ten en cuenta que he incluido 2 archivos JavaScript y 2 archivos CSS aquí:

A continuación, vamos a crear el archivo login.php para que guardemos el nombre de usuario y la contraseña dentro de una sesión en el cliente.

1
2
3
<?php
4
//get the form values

5
$username = $_POST['login_username'];
6
$userpass = $_POST['login_password'];
7
8
9
session_start();
10
$_SESSION['username'] = $username;
11
$_SESSION['userpass'] = $userpass;
12
header('Location: todo.php');
13
exit();

Aquí, simplemente iniciamos una sesión para el usuario, basada en la combinación de nombre de usuario y contraseña que el usuario proporcionará. Esto actúa como una simple combinación de teclas, que permitirá al usuario acceder a los elementos TODO almacenados para una combinación específica de ambos, el nombre de usuario y la contraseña. Luego, redirigimos a todo.php, donde comenzamos a interactuar con el servidor API. Sin embargo, antes de comenzar a codificar el archivo todo.php, primero debemos crear una clase llamada ApiCaller, que encapsulará todos los métodos de llamadas API que necesitaremos, incluido el cifrado de las solicitudes.

Crea apicaller.php y pon lo siguiente dentro:

1
2
3
<?php
4
class ApiCaller
5
{
6
	//some variables for the object

7
	private $_app_id;
8
	private $_app_key;
9
	private $_api_url;
10
	
11
	//construct an ApiCaller object, taking an

12
	//APP ID, APP KEY and API URL parameter

13
	public function __construct($app_id, $app_key, $api_url)
14
	{
15
		$this->_app_id = $app_id;
16
		$this->_app_key = $app_key;
17
		$this->_api_url = $api_url;
18
	}
19
	
20
	//send the request to the API server

21
	//also encrypts the request, then checks

22
	//if the results are valid

23
	public function sendRequest($request_params)
24
	{
25
		//encrypt the request parameters

26
		$enc_request = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->_app_key, json_encode($request_params), MCRYPT_MODE_ECB));
27
		
28
		//create the params array, which will

29
		//be the POST parameters

30
		$params = array();
31
		$params['enc_request'] = $enc_request;
32
		$params['app_id'] = $this->_app_id;
33
		
34
		//initialize and setup the curl handler

35
		$ch = curl_init();
36
		curl_setopt($ch, CURLOPT_URL, $this->_api_url);
37
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
38
		curl_setopt($ch, CURLOPT_POST, count($params));
39
		curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
40
41
		//execute the request

42
		$result = curl_exec($ch);
43
		
44
		//json_decode the result

45
		$result = @json_decode($result);
46
		
47
		//check if we're able to json_decode the result correctly

48
		if( $result == false || isset($result['success']) == false ) {
49
			throw new Exception('Request was not correct');
50
		}
51
		
52
		//if there was an error in the request, throw an exception

53
		if( $result['success'] == false ) {
54
			throw new Exception($result['errormsg']);
55
		}
56
		
57
		//if everything went great, return the data

58
		return $result['data'];
59
	}
60
}

Usaremos la clase ApiCaller para enviar solicitudes a nuestro servidor API. De esta forma, todo el cifrado necesario y el código de inicialización de cURL estarán en un solo lugar, y no tendremos que repetir nuestro código.

  • la función __construct tiene tres parámetros:
    1. $app_id: la APP ID para el cliente (que es APP001 para el cliente del navegador)
    2. $app_key - la APP KEY para el cliente (que es 28e336ac6c9423d946ba02d19c6a2632 para el cliente del navegador)
    3. $api_url: la URL del servidor API, que es http://localhost/simpletodo_api/
  • la función sendRequest():
    1. encripta los parámetros de solicitud usando la biblioteca mcrypt de la misma manera que el servidor API lo descifra
    2. genera los parámetros $_POST que se enviarán al servidor API
    3. ejecuta la llamada API a través de cURL
    4. verifica que el resultado de la llamada API fue exitoso o no
    5. devuelve los datos cuando todo salió según el plan

Ahora, comencemos con la página todo.php. Primero, vamos a crear un código para recuperar la lista actual de artículos pendientes para el usuario nikko con la contraseña test1234 (esta es la combinación de usuario / contraseña que usamos antes para probar el servidor API).

1
2
3
<?php
4
session_start();
5
include_once 'apicaller.php';
6
7
$apicaller = new ApiCaller('APP001', '28e336ac6c9423d946ba02d19c6a2632', 'http://localhost/simpletodo_api/');
8
9
$todo_items = $apicaller->sendRequest(array(
10
	'controller' => 'todo',
11
	'action' => 'read',
12
	'username' => $_SESSION['username'],
13
	'userpass' => $_SESSION['userpass']
14
));
15
16
echo '';
17
var_dump($todo_items);

Ve a la página index.php, inicia sesión como nikko/test1234, y deberías ver un var_dump() del elemento TODO que creamos anteriormente.

TODO item var_dump()

¡Felicitaciones, has realizado una llamada API al servidor API con éxito! En este código, tenemos:

  • comenzar la sesión, así que tenemos acceso al username y userpass en $_SESSION
  • instanciar una nueva clase ApiCaller, dándole la APP ID, la APP SECRET y la URL del servidor API
  • enviar una solicitud a través del método sendRequest()

Ahora, volvamos a formatear los datos para que se vea mejor. Agrega el siguiente código HTML en todo.php. ¡No olvides eliminar el var_dump()!

1
2
3
<!DOCTYPE html>
4
<html>
5
<head>
6
	<title>SimpleTODO</title>
7
	
8
	<link rel="stylesheet" href="css/reset.css" type="text/css" />
9
	<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
10
	<link rel="stylesheet" href="css/flick/jquery-ui-1.8.16.custom.css" type="text/css" />
11
	
12
	<script src="js/jquery.min.js"></script>
13
	<script src="js/jquery-ui-1.8.16.custom.min.js"></script>
14
	
15
	<style>
16
	body {
17
		padding-top: 40px;
18
	}
19
	#main {
20
		margin-top: 80px;
21
	}
22
	
23
	.textalignright {
24
		text-align: right;
25
	}
26
	
27
	.marginbottom10 {
28
		margin-bottom: 10px;
29
	}
30
	#newtodo_window {
31
		text-align: left;
32
		display: none;
33
	}
34
	</style>
35
	
36
	<script>
37
	$(document).ready(function() {
38
		$("#todolist").accordion({
39
			collapsible: true
40
		});
41
		$(".datepicker").datepicker();
42
		$('#newtodo_window').dialog({
43
			autoOpen: false,
44
			height: 'auto',
45
			width: 'auto',
46
			modal: true
47
		});
48
		$('#newtodo').click(function() {
49
			$('#newtodo_window').dialog('open');
50
		});
51
	});
52
	</script>
53
</head>
54
<body>
55
	<div class="topbar">
56
		<div class="fill">
57
			<div class="container">
58
				<a class="brand" href="index.php">SimpleTODO</a>
59
			</div>
60
		</div>
61
	</div>
62
	<div id="main" class="container">
63
		<div class="textalignright marginbottom10">
64
			<span id="newtodo" class="btn info">Create a new TODO item</span>
65
			<div id="newtodo_window" title="Create a new TODO item">
66
				<form method="POST" action="new_todo.php">
67
					<p>Title:<br /><input type="text" class="title" name="title" placeholder="TODO title" /></p>
68
					<p>Date Due:<br /><input type="text" class="datepicker" name="due_date" placeholder="MM/DD/YYYY" /></p>
69
					<p>Description:<br /><textarea class="description" name="description"></textarea></p>
70
					<div class="actions">
71
						<input type="submit" value="Create" name="new_submit" class="btn primary" />
72
					</div>
73
				</form>
74
			</div>
75
		</div>
76
		<div id="todolist">
77
			<?php foreach($todo_items as $todo): ?>
78
			<h3><a href="#"><?php echo $todo->title; ?></a></h3>
79
			<div>
80
				<form method="POST" action="update_todo.php">
81
				<div class="textalignright">
82
					<a href="delete_todo.php?todo_id=<?php echo $todo->todo_id; ?>">Delete</a>
83
				</div>
84
				<div>
85
					<p>Date Due:<br /><input type="text" id="datepicker_<?php echo $todo->todo_id; ?>" class="datepicker" name="due_date" value="12/09/2011" /></p>
86
					<p>Description:<br /><textarea class="span8" id="description_<?php echo $todo->todo_id; ?>" class="description" name="description"><?php echo $todo->description; ?></textarea></p>
87
				</div>
88
				<div class="textalignright">
89
					<?php if( $todo->is_done == 'false' ): ?>
90
					<input type="hidden" value="false" name="is_done" />
91
					<input type="submit" class="btn" value="Mark as Done?" name="markasdone_button" />
92
					<?php else: ?>
93
					<input type="hidden" value="true" name="is_done" />
94
					<input type="button" class="btn success" value="Done!" name="done_button" />
95
					<?php endif; ?>
96
					<input type="hidden" value="<?php echo $todo->todo_id; ?>" name="todo_id" />
97
					<input type="hidden" value="<?php echo $todo->title; ?>" name="title" />
98
					<input type="submit" class="btn primary" value="Save Changes" name="update_button" />
99
				</div>
100
				</form>
101
			</div>
102
			<?php endforeach; ?>
103
		</div>
104
	</div>
105
</body>
106
</html>

Ahora debería verse como esto:

TODO HomeTODO HomeTODO Home

Genial, ¿eh? Pero esto actualmente no hace nada, así que comencemos a agregar algunas funcionalidades. Proporcionaré el código para new_todo.php, que llamará a todo/create para crear un nuevo elemento en el TODO. Crear las otras páginas (update_todo.php y delete_todo.php) debería ser muy similar a este, así que dejo que tú lo crees. Abre new_todo.php y agrega el siguiente código:

1
2
3
<?php
4
session_start();
5
include_once 'apicaller.php';
6
7
$apicaller = new ApiCaller('APP001', '28e336ac6c9423d946ba02d19c6a2632', 'http://localhost/simpletodo_api/');
8
9
$new_item = $apicaller->sendRequest(array(
10
	'controller' => 'todo',
11
	'action' => 'create',
12
	'title' => $_POST['title'],
13
	'due_date' => $_POST['due_date'],
14
	'description' => $_POST['description'],
15
	'username' => $_SESSION['username'],
16
	'userpass' => $_SESSION['userpass']
17
));
18
19
header('Location: todo.php');
20
exit();
21
?>

Como puedes ver, la página new_todo.php usa ApiCaller nuevamente para facilitar el envío de la solicitud todo/create al servidor API. Esto básicamente hace lo mismo que antes:

  • iniciar una sesión para que tenga acceso al $username y $userpass guardados en $_SESSION
  • instanciar una nueva clase ApiCaller, dándole la APP ID, la APP KEY y la URL del servidor API
  • enviar la solicitud a través del método sendRequest()
  • redirigir a todo.php
New TODO!New TODO!New TODO!

Felicidades, ¡funciona! ¡Has creado con éxito una aplicación centrada en API!


Conclusión

Hay tantas ventajas para desarrollar una aplicación que se base en una API. ¿Deseas crear una versión Android de la aplicación SimpleTODO? Toda la funcionalidad que necesitarías ya está en el servidor API, ¡así que todo lo que necesitas hacer es crear el cliente! ¿Deseas refactorizar u optimizar algunas de las clases? No hay problema —  solo asegúrate de que la salida sea la misma. ¿Necesitas agregar más funcionalidades? ¡Puedes hacerlo sin afectar el código del cliente!

Aunque hay algunas desventajas, como tiempos de desarrollo más largos o más complejidad, las ventajas de desarrollar una aplicación web de esta manera superan con creces las desventajas. Depende de nosotros aprovechar este tipo de desarrollo hoy para que podamos cosechar los beneficios más adelante.

¿Estás planeando usar un servidor API para tu próxima aplicación web o ya utilizaste la misma técnica para un proyecto en el pasado? ¡Házmelo saber en los comentarios!