Configuración de Colecciones y Recursos en API Laravel
Resumen
¿Cómo retornar una colección de datos en una API?
Las APIs son herramientas cruciales en el desarrollo moderno, permitiendo el intercambio eficiente de datos. En este contexto, te mostraré cómo configurar correctamente una API para retornar una colección de datos. Este enfoque te permitirá no solo mejorar el rendimiento, sino también personalizar la información que brindas a tu usuario.
¿Cómo configurar el controlador para una colección?
Iniciamos editando el archivo API.php, donde está configurada nuestra capa de rutas. Allí, crearemos un método denominado index dentro de la versión dos de nuestra API para gestionar esta acción. En el controlador PostController.php, ubicado en la carpeta de la versión dos (v2), utilizamos este método para retornar nuestra colección.
La configuración básica emplea la clase Post, que representa la colección, junto con la paginación correspondiente. Este método permite personalizar los datos que se envían al cliente.
¿Cómo personalizar la respuesta de la colección?
Es crucial diferenciar entre personalizar un único recurso y una colección de recursos. La personalización de la colección se logra configurando un objeto que contenga tanto datos obligatorios como campos adicionales. Por ejemplo, en el objeto meta, podemos incluir información adicional como:
Organización: Indicar la organización a la que pertenece esta API, por ejemplo, Platzi.
Autores: Enumerar los autores o responsables del desarrollo, como el nombre del profesor y Platzi.
Tipo: Especificar el tipo de datos que se retornan, en este caso, "artículos".
¿Cómo asegurar la consistencia en el formato de los datos?
Cuando trabajamos con colecciones, es fundamental que el formato de la respuesta coincida con el de un recurso individual. Para ello, se configuran propiedades dentro de la clase de recursos, utilizando PostRecurso::class. Esto asegura que todos los datos, desde el id hasta la fecha de creación, se muestren correctamente y de manera uniforme en toda la colección.
¿Qué sucede al implementar la versión dos?
La implementación de una nueva versión de tu API permite añadir mejoras sin afectar a los usuarios que aún utilizan versiones anteriores. En este ejemplo, la versión dos ofrece más campos y un mejor formato de datos. En aplicaciones móviles, esto es común, ya que usuarios con versiones actualizadas pueden acceder a funcionalidades y datos mejorados.
Mediante el uso de herramientas como PostMan, podemos verificar que la API responde correctamente y que los datos se personalizan según nuestra configuración. Este enfoque no solo es beneficioso para el rendimiento del sistema, sino que también mejora la experiencia del usuario al obtener datos más ricos y relevantes.
En la ultima version de laravel que es la 8 no requiere agregar el
public $collects = PostResource::class;
Eso es correcto
No es necesario, sin embargo puede ser muy útil en caso de querer llamar a otro recurso que no sea el por defecto :D (querer llamar al postResource de la V1).
A mí me lo ha hecho directamente sin añadir public $collects = PostResource::class; Entiendo que con la versión actual lo pilla directamente.
así es
Es asi, la versión 8 de Laravel ya no necesita esto
Les comparto el código fuente del archivo,
App\Http\Resources\V2\PostCollection.php
<?php
namespace App\Http\Resources\V2;use Illuminate\Http\Resources\Json\ResourceCollection;classPostCollectionextendsResourceCollection{public $collects =PostResource::class;/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/publicfunctiontoArray($request){return['data'=> $this->collection,'meta'=>['organization'=>'Platzi','authors'=>['Italomoralesf','Platzi']],'type'=>'articles'];}}
Compañeros, alguien sabe como solucionar el siguiente error?
He seguido al pie de la letra las intrucciones del curso y en local si funcionan mis peticiones de Postman pero cuando lo subo a internet, me sale el siguiente mensaje:
Cross-OriginRequestBlocked:TheSameOriginPolicy disallows reading the remote resource at http://misitioweb.com/api/v1/publicaciones/.(Reason:CORS header ‘Access-Control-Allow-Origin’ missing).
En un fetch le he enviado las cabeceras, también cree un middleware para los cors dentro del proyecto de la API.
¡Hola!
He visto ese problema varias veces y al parecer existen muchas formas de solucionarlo. Sin embargo, a mi la que me funciono fue la que publiqué en este aporte. Espero que a ti también te pueda servir :)
¡Hola!, déjame darte un contexto sobre qué es esto y cómo solucionarlo:
CORS es una política de Cross Domain (dominios cruzados) que entra en juego cuando un dominio A le hace una petición a un dominio B.
Te lo explico en español jaja, básicamente "dominios cruzados" significa que, tú puedes tener un sitio web: platzi.com y también puedes tener otro php.net, entonces, si platzi.com le hace una petición a php.net entonces se dice que los "dominios están cruzados" porque son dominios diferentes.
Esta política sirve para proteger los datos de un servidor, ya que imagina que un sitio mal intencionado intenta hacerle peticiones a Platzi para obtener sus datos, entonces sería un problema, gracias a CORS, Platzi puede decidir a quién sí y a quién no responderle esa petición, y esto lo hace por medio de CORS.
CORS está presente como un encabezado (o header como le conocemos), los headers son datos que viajan en el encabezado de cualquier petición, por ejemplo, si tú haces una petición post, get, put o delete, estas llevarán consigo un header.
Entonces, ¿por qué en local si funciona y en internet no? Porque en local estás usando el mismo dominio: localhost o 127.0.0.1, y Postman también está usando ese dominio, por tanto, al ser el mismo dominio, no hay dominios cruzados, por lo que CORS no se alarma.
Pero al subirlo a internet los dominios cambian y al hacer una petición los dominios se cruzan y CORS se alarma, entonces tú tienes que permitirle a tu backend que pueda responder solicitudes de cualquier dominio, y esto lo haces por mediod e CORS, en específico, lo haces desde su header.
En Laravel, puedes hacerlo mediante un middleware que modifique los headers:
php artisan make:middleware Cors
Después simplemente en ese middleware (ubicado en app/Http/Middleware/Cors.php) agregas esto en la función handle:
publicfunctionhandle($request,Closure $next){return$next($request)->header('Access-Control-Allow-Origin','*')->header('Access-Control-Allow-Methods','GET, POST, PUT, DELETE, OPTIONS');}
Esto modificará el CORS mediante el header Access-Control-Allow-Origin que se encarga de permitir o denegar orígenes, al ponerle un * significa que tu backend va a permitir cualquier origen, es decir, va a permitir que cualquier persona pueda hacerle un request a tu backend.
El header Access-Control-Allow-Methods va a indicar cuáles son los métodos que estos orígenes tienen permitido ejecutar, en este caso estás permitiendo 5 métodos (básicamente le estás dando permiso de hacer lo que sea)
Ahora que ya tienes el middleware creado hay que registrarlo para que Laravel lo conozca, eso lo haces en el archivo app/Http/Kernel.php, aquí simplemente buscas el array $routeMiddleware y agregas un nuevo elemento, el cual sería tu middleware que acabas de crear:
'cors'=> \App\Http\Middleware\Cors::class,
Básicamente le estás diciendo que tu middleware se llama cors (aunque podrías ponerle cualquier nombre) y que ese middleware es manejado por la clase Middleware de CORS que acabamos de crear.
Después de haberlo creado y haberlo registrado ya solo te queda usaro, puedes usar el middleware desde la ruta (tal como lo hicimos con el auth:sanctum o también puedes usarlo desde el controlador, esto es básicamente para específicarle a Laravel que rutas o que controladores deben implementar ese middleware que permite a cualquier persona hacer un request).
Si lo vas a implementar desde un controlador simplemente a ese controlador debes agregarle un constructor y desde ahí llamar al middleware:
El nombre del middleware es el mismo que le pusiste cuando lo registraste en el Kernel.php
Y listo, con esto ya puedes hacer solicitudes desde cualquier parte, incluso desde Postman, spolo ten en cuenta que cualquier persona puede hacerlo, es decir, puedo llegar yo y desde mi Postman hacerle una solicitud a tu servidor y borrarle algo, es por eso que no es una buena práctica permitir todos los orígenes, y por eso tampoco es buena prática hacerle solicitudes a tu servidor en producción desde Postman jaja, por eso todas las pruebas se hacen en local, pero para propósitos de que practiques, esto te sirve, ¡suerte! :D
Estoy en la versión 9.x de Laravel y no es necesario el
public $collects =PostResource::class;
para que los datos se muestren y ordenen en base al recurso.
Algo interesante. Simplemente luego de tener el archivo de Recursos este funciona en forma automática
Gracias!
Resumen Creacion de API V2
Basicamente repetimos la configuracion inicial para crear una API
creamos el controlador y los "recursos" para personalizar la salida.
Como estamos enviando la información del autor tenemos que agregar esta al modelo del post en App > Models > Post public function user() {
return $this->belongsTo(User::class);
}
como podría tener acceso a una tabla cuando su foreign key esta en otra, en este caso el belongsTo no funciona.
desde companies obtener los packs
Hola!, Tienes que configurar el modelo de la tabla companies para que detecte la relación así como lo hiciste desde packs, los métodos para este caso serían hasMany (tiene muchos) o hasOne (tiene uno) :D