() translation by (you can also view the original English article)



En esta serie Programando Con Yii2, estoy guiando a los lectores en el uso del Framework Yii2 para PHP. Podrías también estar interesado en mi Introducción al Framework Yii, que revisa los beneficios de Yii e incluye una vista general de las novedades en Yii 2.x.
En el tutorial de hoy, revisaré cómo construir una API REST en Yii para conectar tu aplicación a la nube, aplicaciones móviles, y otros servicios. Te guiaré a través de la guía de inicio rápido API REST y proporcionaré contexto y ejemplos de peticiones comunes.
Comenzando Con APIs REST Yii
Construir APIs REST en Yii es de hecho bastante sencillo. Puedes aprovechar el framework MVC existente, pero estás creando un punto de acceso distinto al que pretendes que sea accedido por diferentes tipos de servicios (no visitantes de sitio web).
Los Beneficios del Framework Yii REST
El Framework Yii proporciona soporte amplio y detallada documentación para construir APIs. Aquí hay algunas de las capacidades integradas cuando se construyen APIs:
- Prototitpado rápido con soporte para APIs comunes para Active Record. Esto te permite exponer rápida y fácilmente funcionalidad de modelo de datos CRUD vía una API.
- Respuesta formato negociación (soportando JSON y XML por defecto). Hay soporte integrado para devolver información en formatos comunes de salida.
- Serialización personalizada de objeto con soporte para campos seleccionables de salida. Es sencillo modificar qué datos son devueltos.
- Formato apropiado de colección de datos y validación de errores.
- Soporte para Hypermedia Como El Motor de Estado de Aplicación (HATEOAS)
- Ruteo eficiente con revisión apropiada de verbo HTTP.
- Soporte integrado para los verbos
OPTIONS
yHEAD
. - Autenticación y autorización.
- Cacheo de datos y cacheo HTTP.
- Limitación de tasa.
No tendré oportunidad de tocar todo esto el día de hoy.
Mi Interés en APIs REST
En este episodio, construiré una API para permitirnos manipular la tabla Item que creé en el servicio Twixxr desde este tutorial Twitter API. Pero también estoy planeando construir una API para nuestro enfoque de serie de tutoriales startup, Meeting Planner. Una API segura será necesaria para construir una aplicación iOS para el servicio. La API habilitará comunicación entre la aplicación móvil y el servicio en la nube.
Construyendo el Controlador REST
Con el framework REST de Yii, crearemos un punto final para nuestra API y organizaremos controladores para cada tipo de recurso.
Los recursos son esencialmente los modelos de datos de nuestra aplicación. Estos extienden a yii/base/Model.
La clase yii\rest\UrlRule proporciona mapear por ruteo nuestro modelo de datos para puntos finales CRUD API:



Creando un Árbol para Actuar como una API Endpoint
En la plantilla Avanzada Yii2, hay un árbol front-end y back-end, y este es extensible. Para separar las características API, crearemos un tercer árbol para actuar únicamente como un punto final API.
El desarrollador Alex Makarov proporciona esta útil guía para crear árboles adicionales que seguí para crear mi tercer árbol:
1 |
$ cp -R backend api |
2 |
$ cp -R environments/dev/backend/ environments/dev/api |
3 |
$ cp -R environments/prod/backend/ environments/prod/api |
Después, usé el editor Atom para hacer una búsqueda global y reemplazar "backend" con "api" en el nuevo árbol api.
Y agregué el alias de api a /common/config/bootstrap.php:
1 |
<?php
|
2 |
Yii::setAlias('@common', dirname(__DIR__)); |
3 |
Yii::setAlias('@frontend', dirname(dirname(__DIR__)) . '/frontend'); |
4 |
Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend'); |
5 |
Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api'); |
6 |
Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console'); |
7 |
Yii::setAlias('@twixxr', dirname(dirname(__DIR__)) . '/twixxr'); |
Configurando el ruteo de URL para Peticiones Entrantes
En /api/config/main.php, necesitamos agregar el request[]
para configurar análisis JSON y UrlRule
para asociar métodos para los modelos y sus puntos finales.
1 |
return [ |
2 |
'id' => 'app-api', |
3 |
'basePath' => dirname(__DIR__), |
4 |
'controllerNamespace' => 'api\controllers', |
5 |
'bootstrap' => ['log'], |
6 |
'modules' => [], |
7 |
'components' => [ |
8 |
'request' => [ |
9 |
'parsers' => [ |
10 |
'application/json' => 'yii\web\JsonParser', |
11 |
],
|
12 |
],
|
13 |
'urlManager' => [ |
14 |
'enablePrettyUrl' => true, |
15 |
'enableStrictParsing' => true, |
16 |
'showScriptName' => false, |
17 |
'rules' => [ |
18 |
['class' => 'yii\rest\UrlRule', 'controller' => 'item'], |
19 |
['class' => 'yii\rest\UrlRule', 'controller' => 'user'], |
20 |
],
|
21 |
],
|
Eso es básicamente lo que toma habilitar algo de funcionalidad API rica para estos modelos.
Ejemplos Con cURL
Comencemos a hacer peticiones.
Pidiendo OPTIONS
Muéstrame métodos API disponibles:
1 |
curl -i -H "Accept: application/json" |
2 |
-X OPTIONS "http://localhost:8888/api/items" |
Aquí está la respuesta (GET, POST, HEAD, OPTIONS
):
1 |
HTTP/1.1 200 OK |
2 |
Date: Tue, 25 Oct 2016 20:23:10 GMT |
3 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
4 |
X-Powered-By: PHP/7.0.10 |
5 |
Allow: GET, POST, HEAD, OPTIONS |
6 |
Content-Length: 0 |
7 |
Content-Type: application/json; charset=UTF-8 |
Peticiones GET
Petición: ¿Cuántos datos hay ahí?
1 |
curl -i --head "http://localhost:8888/api/items" |
Respuesta: 576 registros a lo largo de 29 páginas...
1 |
HTTP/1.1 200 OK |
2 |
Date: Tue, 25 Oct 2016 23:17:37 GMT |
3 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
4 |
X-Powered-By: PHP/7.0.10 |
5 |
X-Pagination-Total-Count: 576 |
6 |
X-Pagination-Page-Count: 29 |
7 |
X-Pagination-Current-Page: 1 |
8 |
X-Pagination-Per-Page: 20 |
9 |
Link: <http://localhost:8888/api/items?page=1>; rel=self, <http://localhost:8888/api/items?page=2>; rel=next, <http://localhost:8888/api/items?page=29>; rel=last |
10 |
Content-Type: application/json; charset=UTF-8 |
Petición: Muéstrame el registro 15:
1 |
curl -i "http://localhost:8888/api/items/15" |
Respuesta:
1 |
HTTP/1.1 200 OK |
2 |
Date: Tue, 25 Oct 2016 23:19:27 GMT |
3 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
4 |
X-Powered-By: PHP/7.0.10 |
5 |
Content-Length: 203 |
6 |
Content-Type: application/json; charset=UTF-8 |
7 |
|
8 |
{"id":15,"title":"Jeff Reifman","path":"jeffreifman", |
9 |
"detail":"","status":0,"posted_by":1,"image_url":"", |
10 |
"favorites":0,"stat_1":0,"stat_2":0,"stat_3":0,"created_at":1477277956,"updated_at":1477277956} |
Petición: Muéstrame todos los datos en la página 3:
1 |
curl -i -H "Accept:application/json" |
2 |
"http://localhost:8888/api/items?page=3"
|
Respuesta:
1 |
HTTP/1.1 200 OK |
2 |
Date: Tue, 25 Oct 2016 23:30:21 GMT |
3 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
4 |
X-Powered-By: PHP/7.0.10 |
5 |
X-Pagination-Total-Count: 575 |
6 |
X-Pagination-Page-Count: 29 |
7 |
X-Pagination-Current-Page: 3 |
8 |
X-Pagination-Per-Page: 20 |
9 |
Link: <http://localhost:8888/api/items?page=3>; rel=self, <http://localhost:8888/api/items?page=1>; rel=first, <http://localhost:8888/api/items?page=2>; rel=prev, <http://localhost:8888/api/items?page=4>; rel=next, <http://localhost:8888/api/items?page=29>; rel=last |
10 |
Content-Length: 3999 |
11 |
Content-Type: application/json; charset=UTF-8 |
12 |
|
13 |
[{"id":43,"title":"_jannalynn","path":"_jannalynn", |
14 |
"detail":"","status":0,"posted_by":1,"image_url":"", |
15 |
"favorites":0,"stat_1":0,"stat_2":0,"stat_3":0, |
16 |
... |
17 |
... |
18 |
... |
19 |
{"id":99,"title":"alibrown","path":"alibrown","detail":"", |
20 |
"status":0,"posted_by":1,"image_url":"","favorites":0, |
21 |
"stat_1":0,"stat_2":0,"stat_3":0,"created_at":1477277956, |
22 |
"updated_at":1477277956}] |
Peticiones DELETE
Aquí está un ejemplo de una petición GET seguida por una petición DELETE y después un seguimiento fallido de intento GET:
1 |
$ curl -i -H "Accept: application/json" "http://localhost:8888/api/items/8" |
2 |
HTTP/1.1 200 OK |
3 |
Date: Tue, 25 Oct 2016 23:32:17 GMT |
4 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
5 |
X-Powered-By: PHP/7.0.10 |
6 |
Content-Length: 186 |
7 |
Content-Type: application/json; charset=UTF-8 |
8 |
|
9 |
{"id":8,"title":"aaker","path":"aaker","detail":"","status":0,"posted_by":1,"image_url":"","favorites":0,"stat_1":0,"stat_2":0,"stat_3":0,"created_at":1477277956,"updated_at":1477277956} |
10 |
|
11 |
$ curl -i -H "Accept: application/json" -X DELETE "http://localhost:8888/api/items/8" |
12 |
HTTP/1.1 204 No Content |
13 |
Date: Tue, 25 Oct 2016 23:32:26 GMT |
14 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
15 |
X-Powered-By: PHP/7.0.10 |
16 |
Content-Length: 0 |
17 |
Content-Type: application/json; charset=UTF-8 |
18 |
|
19 |
$ curl -i -H "Accept: application/json" "http://localhost:8888/api/items/8" |
20 |
HTTP/1.1 404 Not Found |
21 |
Date: Tue, 25 Oct 2016 23:32:28 GMT |
22 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
23 |
X-Powered-By: PHP/7.0.10 |
24 |
Content-Length: 115 |
25 |
Content-Type: application/json; charset=UTF-8 |
26 |
|
27 |
{"name":"Not Found","message":"Object not found: 8","code":0,"status":404,"type":"yii\\web\\NotFoundHttpException"} |
Las peticiones para un registro borrado devuelven un error 404.
Peticiones POST
Para mis peticiones post, cambié a la app de Chrome Postman:



Registrarse para Postman fue sencillo:



Y después pude enviar peticiones a mi API localhost en una GUI más amigable:



Después, recuperé los datos vía curl, record 577
:
1 |
$ curl -i -H "Accept: application/json" "http://localhost:8888/api/items/577" |
2 |
HTTP/1.1 200 OK |
3 |
Date: Tue, 25 Oct 2016 23:40:44 GMT |
4 |
Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.12 PHP/7.0.10 mod_ssl/2.2.31 OpenSSL/1.0.2h DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 |
5 |
X-Powered-By: PHP/7.0.10 |
6 |
Content-Length: 219 |
7 |
Content-Type: application/json; charset=UTF-8 |
8 |
|
9 |
{"id":577,"title":"Jeff Reifman","path":"reifman", |
10 |
"detail":"A programmer on earth.","status":0, |
11 |
"posted_by":1,"image_url":"","favorites":0, |
12 |
"stat_1":0,"stat_2":0,"stat_3":0,"created_at":1477436477, |
13 |
"updated_at":1477436477} |
Postman resultó esencial para redondear mis pruebas ya que la linea de comando curl no es sencilla de configurar para envíos POST.
Mirando Hacia Adelante
En adición a su resumen de inicio rápido REST, la documentación Yii 2.0 proporciona detalle en un arreglo de otros aspectos de creación de API:
- Recursos
- Controladores
- Ruteo
- Formato de Respuesta
- Autenticación
- Limitación de Tasa
- Versionamiento
- Manejo de Errores
Espero tener la oportunidad de explorar más de estos en futuros episodios. Pero ciertamente, uno de los siguientes pasos es crear una API para Meeting Planner en la serie startup.
En conclusión, construir una API REST básica con el framework MVC Yii es bastante simple. El equipo de Yii ha hecho un gran trabajo estandarizando funcionalidad para un requerimiento muy importante, APIs REST. Espero que hayas disfrutado aprender sobre ellas.
Si tienes cualquier pregunta o sugerencia, por favor publícalas en los comentarios. Si quisieras seguir a la par con mis tutoriales Envato Tuts+ futuros y otras series, por favor visita mi página de instructor o sígueme @reifman. Definitivamente revisa mi serie startup y Meeting Planner.