jueves, 22 de agosto de 2013

PHP y cURL (libcurl)

En el tutorial anterior, se explicó el funcionamiento de la herramienta cURL para utilizarla en el interprete de comandos. Ahora vamos a ver como podemos utilizar esa misma herramienta en nuestros scripts PHP.
Para ello utilizaremos la librería de PHP libcurl. Si en nuestra configuración de PHP no la tenemos activa, simplemente modificaremos php.ini y evidentemente reiniciaremos el servidor Apache. Si por el contrario no la tenemos instalada (se puede comprobar con la función phpinfo() en un script), seguiremos las siguientes instrucciones:

 sudo apt-get install php5-curl  
 sudo service apache2 restart //tras cualquier cambio en PHP o mysql es necesario reiniciar el servidor  

Ahora centrémonos en como utilizar la librería en PHP.

Como ocurre cuando conectamos con una base de datos o abrimos un fichero, necesitamos un manejador que obtendremos con la función de inicialización de la librería. Esto lo haremos con la función curl_init. Esta función devuelve false en caso de error o el manejador (handle) en caso de éxito. Este manejador estará disponible hasta que se llame a la función curl_close.
En el propio curl_init podemos indicar la URL a la que queremos hacer una petición. Aunque como veremos posteriormente, la URL también se puede indicar a través de otra función de la librería.
Pues bien, una vez inicializada la petición podemos pasar a ejecutarla con la función curl_exec y almacenar el resultado para posteriormente trabajar con él. Vamos a ver un sencillo ejemplo:

 <?php  
      $ch = curl_init("http://www.ejemplo.com");  
      curl_exec($ch);  
      curl_close($ch);  
 ?>  

Con esto lo que conseguimos es hacer una petición simple (GET) a la URL. Como no hemos dicho lo contrario se mostrará el resultado de la petición (en el navegador).

Esto puede parecer muy sencillo, sin embargo hay que tener en cuenta que no solo haremos peticiones simples (GET) a un servicio, o puede que tengamos que enviar información extra en la cabeceras de la petición para indicar el user-agent o el idioma... Infinidad de cosas que hacen que necesitemos un mecanismo para poder especificar las diferentes opciones de nuestra petición. Y esto se hace a través de la función  curl_setopt.

La función curl_setopt sigue la siguiente sintaxis:

 bool curl_setopt (resource $handle, int $opcion , mixed $valor );  

Aquí tenemos un listado de las opciones más importantes y posibles valores:

- CURLOPT_URL - Dirección URL a capturar. Este valor también puede ser configurado cuando se inicia una sesión con curl_init(), como hemos visto en el primer ejemplo.

- CURLOPT_COOKIE - Define las cookies que se van a enviar al servidor HTTP, por ejemplo: "cookie1=azul&cookie2=rojo;"

- CURLOPT_COOKIEFILE - Nombre del fichero que contiene datos de las cookies. El fichero también puede estar en un servidor HTTP remoto.

- CURLOPT_COOKIEJAR - Nombre del fichero donde guardar cookies internas cuando se cierre la conexión.

- CURLOPT_PORT - Puerto alternativo con el que conectarse.

- CURLOPT_FOLLOWLOCATION – TRUE para seguir cualquier encabezado "Location: " que el servidor (al que se hace la petición) envíe como parte del encabezado HTTP. PHP seguirá tantos header( "Location: ") como se envíen, a no ser que la opción CURLOPT_MAXREDIRS esté establecida. El valor de la opción CURLOPT_FOLLOWLOCATION será FALSE por defecto.

- CURLOPT_REFERER - Contenido de la cabecera "Referer" (indica el cliente) para ser usado en la petición HTTP.

- CURLOPT_USERAGENT - Nombre del navegador

- CURLOPT_HEADER – True: para incluir las cabeceras de la respuesta de la petición.

- CURLOPT_NOBODY - TRUE para excluir el cuerpo de la respuesta recibida. El método de petición es establecido a HEAD.

- CURLOPT_HTTPHEADER - Un array de campos para configurar las cabeceras HTTP que queremos enviar junto a la petición. Usaremos el formato: array('Content-type: text/plain', 'Content-length: 100'....).

- CURLOPT_POST – True: Para hacer una petición HTTP-POST.

- CURLOPT_POSTFIELDS - Es válido si CURLOPT_POST esta en TRUE. Define los datos del POST, ejemplo: "usuario=luis&password=12345". También podemos utilizar la función  http_build_query() sobre un array de datos para convertirlo en la query string (cadena de consulta) válida para el envío.

- CURLOPT_CUSTOMREQUEST - Método de petición personalizado a usar en lugar de "GET" o "POST". Es útil para hacer "DELETE", 'PUT' u otros tipos de peticiones HTTP menos comunes.

- CURLOPT_RETURNTRANSFER - TRUE para devolver el resultado de la transferencia como cadena (string) del valor de la función curl_exec, en lugar de mostrarlo directamente.

- CURLOPT_TIMEOUT – Establecemos el tiempo máximo de respuesta en segundos.

Vamos a ver unos ejemplos combinando las funciones vistas:

1. Buscar en Google. Esta vez estableceremos la URL a la que hacer la petición GET en la función curl_setopt, mediante la opción CURLOPT_URL.

 <?php  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://www.google.es/search?q=PHP");  
 curl_exec($ch);  
 curl_close($ch);  
 ?>  

2. Indicar el navegador con el que hacemos la petición:

 <?php  
 $ch =curl_init();  
 curl_setopt($ch,CURLOPT_URL, "http://www.ejemplo.com");  
 curl_setopt($curl,CURLOPT_USERAGENT,'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:7.0.1) Gecko/20100101 Firefox/7.0.1');  
 curl_exec($ch);  
 curl_close($ch);  
 ?>  

3. Verificar la existencia de una página web:

 <?php  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://www.direccion.com/");  
 curl_setopt($ch, CURLOPT_HEADER, true);  //queremos las cabeceras de la respuesta
 curl_setopt($ch, CURLOPT_NOBODY, true);  //no queremos el cuerpo de la respuesta
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //el resultado lo almacenaremos en una cadena
 $data = curl_exec($ch);  
 curl_close($ch)  
 echo $data;  
 ?>  

4. Incluir las cabeceras en la salida

 <?php  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://www.example.com");  
 curl_setopt($ch, CURLOPT_HEADER,true);  
 curl_exec($ch);  
 curl_close($ch);  
 ?>  

5. Pedir un listado de usuarios

 <?php  
  $ch = curl_init();  
  curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.com/servicio_rest/usuarios");  
  curl_setopt($ch, CURLOPT_HEADER, false);  
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
  $data = curl_exec($ch);  
  print_r($data);  
  curl_close($ch);  
 ?>  

Supongamos que la respuesta del servicio RESTful es JSON. Mediante la función json_decode podremos convertir la cadena JSON a una variable valida PHP.

 $data = json_decode(curl_exec($ch),true);  

6. Iniciar una sesión en una página. Para ello ahora la petición no será GET sino que tiene que ser POST. por lo tanto lo tendremos que indicar en la las opciones de curl_setopt.

 <?php  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.com/login.php");  
 curl_setopt($ch, CURLOPT_POST, true);  
 curl_setopt($ch, CURLOPT_POSTFIELDS, "usuario=prueba&password=1234;");  
 curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");  
 curl_exec($ch);  
 curl_close($ch);  
 ?>  

También podemos utilizar la función http_build_query para construir una cadena de consulta a partir de un array.

 <?php  
  $postData = array(  
    'usuariol'=>'prueba',  
    'password' =>'1234'  
  );  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.com/login.php");  
 curl_setopt($ch, CURLOPT_POST, true);  
 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));  
 curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");  
 curl_exec($ch);  
 curl_close($ch);  
 ?>  

7. Crear un nuevo usuario en un servicio RESTful. Para ello utilizaremos el método POST, que como se explicó en el tutorial de introducción a los servicios RESTFul, es el método correcto para crear un recurso.

 <?php  
  $postData = array(  
  'nombre'=>'prueba6',  
  'email'=>'prueba6@ejemplo.com',  
  'pwd' =>'1234'  
  );  
  $ch = curl_init();  
  curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.es/servicio_rest/crearUsuario");  
  curl_setopt($ch, CURLOPT_HEADER, false);  
  curl_setopt($ch, CURLOPT_POST, true);  
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));  
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
  $data = curl_exec($ch);  
  print_r($data);  
  curl_close($ch);  
 ?>  

8. Borrar un usuario. Para ello utilizaremos el método DELETE. Que es el método conceptualmente correcto para borrar un recurso.

 <?php  
  $data = array("id"=>3);  
  $ch = curl_init();  
  curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.com/servicio_rest/borrarUsuario");  
  curl_setopt($ch, CURLOPT_HEADER, false);  
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');  
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));  
  $data = curl_exec($ch);  
  print_r($data);  
  curl_close($ch); 
 ?>  

En este ejemplo hemos mostrado que al método de petición 'custom' (DELETE, PUT) también le podemos pasar datos a través de la opción CURLOPT_POSTFIELDS.

También se podría haber optado por una petición DELETE de esta forma:

  <?php  
  $ch = curl_init();   
  curl_setopt($ch, CURLOPT_URL, "http://www.ejemplo.com/servicio_rest/borrarUsuario/3");   
  curl_setopt($ch, CURLOPT_HEADER, false);   
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');   
  $data = curl_exec($ch);   
  print_r($data);   
  curl_close($ch);   
  ?>  

Evidentemente depende de las reglas de reescritura que se apliquen en el servicio al que se hacen las peticiones.

9. Actualizar los datos de un usuario.Utilizaremos el método PUT ya que es el método conceptualmente correcto para actualizar un recurso existente.

 <?php  
 $data = array("nombre" => 'prueba',  
     "id"=>1  
 );  
 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, "http://localhost/servicio_rest/actualizarNombre");  
 curl_setopt($ch, CURLOPT_HEADER, false);  
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");  
 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));  
 $data = curl_exec($ch);  
 print_r($data);  
 curl_close($ch);
 ?>  

En muchos sistemas reales, las funciones que deberían de realizar las peticiones de tipo PUT y DELETE son realizadas por peticiones POST. La petición POST se utiliza tanto para crear, borrar o actualizar un recurso. Y por lo tanto las peticiones PUT y DELETE no son utilizadas.

Entradas relacionadas

Reglas de reescritura - Parte 1: Introducción

6 comentarios:

  1. Gracias por tu tutorial... se puede hacer una funcion con curl para obtener todas las uls de un sitio web?

    ResponderEliminar
  2. He hecho una peticion GET con CURL con las opciones que has comentado, al ejecutarlo en wamp funciona perfecto, devuelve los valores que necesito, pero al subirlo a mi hosting aunque la respuesta es 200 ok, el echo para mostrar los resultados me lanza error 443

    ResponderEliminar