Servicios Web REST y PHP

En este artículo les mostraré cómo implementar una aplicación CRUD con PHP y servicios Web RESTFul. Los requisitos son los siguientes:
  • PHP 4.0 o superior
  • MySQL 4.0 o superior
  • Integración PHP+MySQL realizada correctamente.

Y la estructura de archivos es como se muestra a continuación:

rest_api
|-- dao.php
|-- index.php
|-- model.php
|-- service.php


Como primer paso, crear una base de datos y crear la tabla test con la estructura que se muestra a continuación.


Crear el archivo model.php, en donde se especificará una "clase entidad" que corresponderá con la tabla test de nuestra base de datos [Lo sé, no es java =(]. El hecho de no utilizar el concepto de encapsulación es debido a la versión de PHP que se utilizó para este post (4.0).
<?php

class Test {

    var $id;
    var $nombres;
    var $apellidos;

}
También tendremos una clase PHP exclusivamente para el acceso a base de datos. En el archivo dao.php, se implementarán todas las operaciones sobre base de datos.
<?php

class DAO {

    var $server;
    var $db;
    var $dblog;
    var $dbpass;

    function DAO() {
        $this->server = 'localhost';
        $this->db = 'test';
        $this->dblog = 'root';
        $this->dbpass = '123456';
    }

    function connect() {
        $this->cnn = new MySQL(array('host' => $this->server, 'user' => $this->dblog, 'password' => $this->dbpass, 'database' => $this->db));
    }

    function insert($test) {
        $this->connect();
        $sql = "INSERT INTO test(nombres, apellidos) VALUES ('" . $test->nombres . "','" . $test->apellidos . "'" . ")";
        $rs = $this->cnn->query($sql);
    }

    function findAll() {
        $this->connect();
        $sql = "SELECT * FROM test";
        $result = $this->cnn->query($sql);
        $rs = $result->fetchall(MYSQL_ASSOC);
        return $rs;
    }

    function find($id) {
        $this->connect();
        $sql = "SELECT * FROM test WHERE id=" . $id;
        $result = $this->cnn->query($sql);
        $rs = $result->fetchRow(MYSQL_ASSOC);
        return $rs;
    }

    function update($test) {
        $this->connect();
        $sql = "UPDATE test SET nombres ='" . $test->nombres . "', apellidos='" . $test->apellidos . "' WHERE id='" . $test->id . "'";
        $this->cnn->query($sql);
    }

    function delete($id) {
        $this->connect();
        $sql = "DELETE FROM test WHERE id='" . $id . "'";
        $this->cnn->query($sql);
    }

}
Las funciones de la clase DAO serán invocadas a través de una capa de servicio, la cual se encargará de procesar las peticiones y determinar qué tipo de servicio REST es el consultado. El archivo tendrá el nombre service.php.
<?php

require_once("dao.php");
require_once("model.php");

$method = $_SERVER['REQUEST_METHOD'];

$dao = new DAO();
$json_service = new Services_JSON();

//call DAO based on HTTP method
switch ($method) {
    case 'GET':
        $result = $dao->findAll();
        $json_response = $json_service->encode($result);
        echo $json_response;
        break;
    case 'POST':
        $test = new Test();
        $test->nombres = $_POST['nombres'];
        $test->apellidos = $_POST['apellidos'];
        $dao->insert($test);
        break;
    case 'PUT':
        parse_str(file_get_contents("php://input"), $post_vars);
        $test = new Test();
        $test->id = $post_vars['id'];
        $test->nombres = $post_vars['nombres'];
        $test->apellidos = $post_vars['apellidos'];
        $dao->update($test);
        break;
    case 'DELETE':
        parse_str(file_get_contents("php://input"), $post_vars);
        $id = $post_vars['id'];
        $dao->delete($id);
        break;
}
Finalmente, escribimos la parte de código correspondiente al lado del cliente en el archivo index.php. A través de una URL, accedemos a los servicios publicados y utilizamos sus funcionalidades dependiendo de la manera en cómo los invoquemos. (GET/POST/PUT/DELETE).
<?php

$url = "http://localhost/res_api/service.php";

if (!function_exists('http_build_query')) {

    function http_build_query($data, $prefix = null, $sep = '', $key = '') {
        $ret = array();
        foreach ((array) $data as $k => $v) {
            $k = urlencode($k);
            if (is_int($k) && $prefix != null) {
                $k = $prefix . $k;
            }

            if (!empty($key)) {
                $k = $key . "[" . $k . "]";
            }

            if (is_array($v) || is_object($v)) {
                array_push($ret, http_build_query($v, "", $sep, $k));
            } else {
                array_push($ret, $k . "=" . urlencode($v));
            }
        }

        if (empty($sep)) {
            $sep = ini_get("arg_separator.output");
        }

        return implode($sep, $ret);
    }

}

/* GET Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($client);
echo $curl_response;

/* POST Client */
$curl_post_data = array(
    'nombres' => 'Roger Manuel',
    'apellidos' => 'Rodriguez Alfaro'
);
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($client, CURLOPT_POST, 1);
curl_setopt($client, CURLOPT_POSTFIELDS, $curl_post_data);
$curl_response = curl_exec($client);
echo $curl_response;

/* PUT Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, true);
curl_setopt($client, CURLOPT_CUSTOMREQUEST, "PUT");
$curl_put_data = array(
    'id' => '14',
    'nombres' => 'Enma',
    'apellidos' => 'Cruz Ticle'
);
curl_setopt($client, CURLOPT_POSTFIELDS, http_build_query($curl_put_data));
$curl_response = curl_exec($client);
if ($response === false) {
    $info = curl_getinfo($client);
    curl_close($client);
    die('error occured during curl exec. Additioanl info: ' . var_export($info));
}
curl_close($client);
echo $curl_response;


/* DELETE Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, true);
curl_setopt($client, CURLOPT_CUSTOMREQUEST, "DELETE");
$curl_post_data = array(
    'id' => '15'
);
curl_setopt($client, CURLOPT_POSTFIELDS, http_build_query($curl_post_data));
$curl_response = curl_exec($client);
curl_close($client);
echo $curl_response;
Evidentemente, estaría restando la parte de la vista, pero eso ya será tema de otro post. Recuerden que es mi primer post de PHP, por lo que les pido comprensión si algunos conceptos o separaciones de capas no las hago correctamente, la idea es aportar no? :D

Comentarios