En este tutorial, crearemos una api json crud completa utilizando Laravel y la nueva función de recursos de la API de Eloquent. Este enfoque se usa cuando desea construir todo el back-end de su aplicación usando Laravel, mientras deja el front-end a Vue, React o Angular. Al utilizar Laravel y Eloquent API Resources, puede formatear sus respuestas de datos como desee y al mismo tiempo agregar metainformación, enlaces e información de paginación, envoltura de datos personalizados, atributos condicionales y relaciones.
Entorno de desarrollo local
Aquí acabamos de configurar un nuevo proyecto llamado lpgvue
para comenzar. ¿Por qué ese nombre? Es la abreviatura de Laravel Play Ground / Vue. Básicamente, solo queremos tener un entorno de desarrollo local que nos permita configurar la última y mejor versión de Lavavel para que podamos construir y modificar como queramos.
composer global require laravel / installer
composer create-project –prefer-dist laravel / laravel lpgvue
composer require –dev barryvdh / laravel-ide-helper
php artisan ide-helper: generate
Con los comandos anteriores, ahora tenemos un proyecto Laravel fresco y agradable para trabajar.
Crear datos para trabajar
Laravel hace que sea realmente fácil crear tablas para almacenar datos de muestra para trabajar. Además de las migraciones, puede configurar la inicialización de la base de datos para llenar rápidamente esas tablas con datos para que pueda probar su API.
Agregar una base de datos
Primero agregamos una base de datos a nuestro servidor usando una herramienta de interfaz gráfica de usuario. Consulte la configuración de su base de datos para Laravel para obtener más información.
Estamos utilizando Homestead, por supuesto, el Vagrant Box de primera calidad disponible para entornos de desarrollo local. Eso significa que nuestro nombre de usuario y contraseña son homestead y secretos respectivamente. Sin embargo, necesitamos especificar la base de datos que acabamos de crear en el archivo env.
Agregar una migración
Podemos usar Artisan para generar una migración que proporcionará el esquema para una tabla de publicaciones que contendrá nuestras publicaciones.
php artisan make: migración create_posts_table –create = posts
En las líneas resaltadas a continuación, agregamos campos para title
y body
de las publicaciones.
base de datos / migraciones / xxxx_xx_xx_xxxxxx_create_posts_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePostsTable extends Migration { public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('title'); $table->text('body'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('posts'); } } |
Semilla de base de datos
Para habilitar la siembra de bases de datos, podemos usar Artisan nuevamente para crear una clase de sembradora para nosotros.
php artisan make: seeder PostsTableSeeder
El código que agregamos a continuación especifica hacer 25 publicaciones de muestra en la base de datos.
base de datos / semillas / PostsTableSeeder.php
| <?php use Illuminate\Database\Seeder; class PostsTableSeeder extends Seeder { public function run() { factory(App\Post::class, 25)->create(); } } |
También necesitamos actualizar el archivo DatabaseSeeder.php para ahora hacer uso de la clase PostsTableSeeder.
base de datos / semillas / DatabaseSeeder.php
| <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { public function run() { $this->call(PostsTableSeeder::class); } } |
php artisan make: factory PostFactory
Finalmente, necesitamos una Fábrica que nos permita especificar la forma de los datos que poblarán la base de datos. Queremos que el título utilice 40 caracteres y el cuerpo 200 caracteres. Para configurar algo como esto, simplemente siga estos pasos.
base de datos / fábricas / PostFactory.php
| <?php /* @var $factory \Illuminate\Database\Eloquent\Factory */ use App\Post; use Faker\Generator as Faker; $factory->define(Post::class, function (Faker $faker) { return [ 'title' => $faker->text(40), 'body' => $faker->text(200) ]; }); |
Crear un modelo de datos
La aplicación también necesitará un modelo para la tabla de publicaciones. Podríamos haber hecho el modelo y la migración de una sola vez, pero este enfoque también funcionará.
php artisan make: modelo Post
Con eso, toda la configuración de datos está completa. Ahora, queremos migrar la base de datos y luego sembrar la base de datos. ¡Aquí vamos!
php artisan migrate
php artisan db: semilla
Debería ver mensajes sobre las migraciones que se ejecutan correctamente y la inicialización de la base de datos se completa correctamente. Ahora, cuando se visualiza la base de datos con una herramienta GUI, todos los datos de muestra ahora se completan.
Controladores y rutas de edificios
¡Ahora podemos comenzar a construir el código y los archivos reales que impulsarán la API REST! Primero, necesitamos un controlador Post basado en recursos. Artisan lo hace fácil.
Crear un controlador
php artisan make: controller PostController –resource
El archivo resultante está a continuación con los comentarios y un par de métodos eliminados. Para nuestro pequeño tutorial usaremos index (), store (), show () y destroy ().
aplicación / Http / Controllers / PostController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class PostController extends Controller { public function index() { // } public function store(Request $request) { // } public function show($id) { // } public function destroy($id) { // } } |
Configurar el archivo de rutas
Laravel te da dos puntos de entrada para rutas. Uno es para solicitudes web estándar y el otro está diseñado para solicitudes de API. Estamos creando una API aquí, por lo que necesitamos completar nuestras rutas en el archivo api.php. El código está a continuación con comentarios que explican el propósito de cada ruta.
rutas / api.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php use Illuminate\Http\Request; // List all posts Route::get('posts', 'PostController@index'); // List a single post Route::get('post/{id}', 'PostController@show'); // Create a new post Route::post('post', 'PostController@store'); // Update a post Route::put('post', 'PostController@store'); // Delete a post Route::delete('post/{id}', 'PostController@destroy'); |
Observe que hay dos rutas que apuntan al mismo método store (). Esto se debe a que el método store () puede actualizar una publicación cuando se usa el verbo http PUT o crear una nueva publicación cuando se usa el verbo http POST. Cosas bastante interesantes.
Crear un recurso de API
Ahora podemos empezar a trabajar con recursos API en Laravel. La documentación describe esta característica como un tipo de capa de transformación que vive entre la capa del modelo de datos y la capa de respuesta JSON. Podemos seguir adelante y crear un nuevo recurso API como ese.
php artisan make: publicación de recursos
El comando anterior crea una nueva carpeta de Recursos y llena el siguiente archivo.
aplicación / Http / Resources / Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class Post extends JsonResource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return parent::toArray($request); } } |
Este archivo es su tipo de Transformer que le permite personalizar los datos de respuesta JSON de su api de varias maneras. Podemos ponerlo en práctica ahora.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Http\Resources\Post as PostResource; class PostController extends Controller { public function index() { // Get the posts $posts = Post::paginate(5); // Return collection of posts as a resource return PostResource::collection($posts); } public function store(Request $request) { // } public function show($id) { // } public function destroy($id) { // } } |
Ahora podemos visitar http://lpgvue.io/api/posts
en el navegador y ver la salida JSON bien formateada. Los datos están muy bien contenidos en la propiedad de datos, junto con enlaces para paginación y metainformación. ¡Muy genial!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | { "data": [ { "id": 1, "title": "Sunt quis iure est deserunt ut.", "body": "Eos eum accusantium totam maiores ipsum autem recusandae. Dolores in qui officiis culpa eligendi quas. Cupiditate earum perferendis qui quia.", "created_at": "2019-05-13 15:43:06", "updated_at": "2019-05-13 15:43:06" }, { "id": 2, "title": "Enim ut cupiditate dolorum quos enim.", "body": "Mollitia sequi tempora cupiditate quia. Mollitia aliquid nesciunt provident. Nam reiciendis delectus a est repellendus omnis ut occaecati.", "created_at": "2019-05-13 15:43:06", "updated_at": "2019-05-13 15:43:06" }, { "id": 3, "title": "Nihil libero nam quisquam optio.", "body": "Aut vitae ut deserunt beatae magnam eaque. Eaque quam rerum dolores ea tempore sint ipsa. Velit mollitia sapiente a. Et ratione quam soluta odit ullam fugit dolores voluptatum.", "created_at": "2019-05-13 15:43:06", "updated_at": "2019-05-13 15:43:06" }, { "id": 4, "title": "Quis esse a sit est.", "body": "Corporis tempore autem optio odit atque sed. Cupiditate adipisci recusandae doloribus quas. Tempora qui sequi error rerum aperiam voluptas.", "created_at": "2019-05-13 15:43:06", "updated_at": "2019-05-13 15:43:06" }, { "id": 5, "title": "Nam velit doloribus cumque qui cumque.", "body": "Voluptates culpa quidem omnis soluta animi eaque. Nihil voluptates voluptas quis cum adipisci tenetur. Eveniet voluptatem quo velit ea occaecati ducimus sed.", "created_at": "2019-05-13 15:43:06", "updated_at": "2019-05-13 15:43:06" } ], "links": { "first": "http://lpgvue.io/api/posts?page=1", "last": "http://lpgvue.io/api/posts?page=5", "prev": null, "next": "http://lpgvue.io/api/posts?page=2" }, "meta": { "current_page": 1, "from": 1, "last_page": 5, "path": "http://lpgvue.io/api/posts", "per_page": 5, "to": 5, "total": 25 } } |
Personalización de los datos devueltos
El recurso generado que creamos anteriormente se puede personalizar para que pueda devolver exactamente lo que le gusta de la API. Al modificar la declaración de devolución como lo hacemos a continuación, ahora solo se envían la identificación, el título y el cuerpo, lo que limpia las cosas con solo un toque.
aplicación / Http / Resources / Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class Post extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'title' => $this->title, 'body' => $this->body ]; } } |
Aquí está la salida resultante al visitar http://lpgvue.io/api/posts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | { "data": [ { "id": 1, "title": "Sunt quis iure est deserunt ut.", "body": "Eos eum accusantium totam maiores ipsum autem recusandae. Dolores in qui officiis culpa eligendi quas. Cupiditate earum perferendis qui quia." }, { "id": 2, "title": "Enim ut cupiditate dolorum quos enim.", "body": "Mollitia sequi tempora cupiditate quia. Mollitia aliquid nesciunt provident. Nam reiciendis delectus a est repellendus omnis ut occaecati." }, { "id": 3, "title": "Nihil libero nam quisquam optio.", "body": "Aut vitae ut deserunt beatae magnam eaque. Eaque quam rerum dolores ea tempore sint ipsa. Velit mollitia sapiente a. Et ratione quam soluta odit ullam fugit dolores voluptatum." }, { "id": 4, "title": "Quis esse a sit est.", "body": "Corporis tempore autem optio odit atque sed. Cupiditate adipisci recusandae doloribus quas. Tempora qui sequi error rerum aperiam voluptas." }, { "id": 5, "title": "Nam velit doloribus cumque qui cumque.", "body": "Voluptates culpa quidem omnis soluta animi eaque. Nihil voluptates voluptas quis cum adipisci tenetur. Eveniet voluptatem quo velit ea occaecati ducimus sed." } ], "links": { "first": "http://lpgvue.io/api/posts?page=1", "last": "http://lpgvue.io/api/posts?page=5", "prev": null, "next": "http://lpgvue.io/api/posts?page=2" }, "meta": { "current_page": 1, "from": 1, "last_page": 5, "path": "http://lpgvue.io/api/posts", "per_page": 5, "to": 5, "total": 25 } } |
Asignación de campo de base de datos a respuesta de API
Esta característica del recurso API de Laravel es realmente genial. Los campos de su base de datos no tienen que coincidir exactamente con las claves utilizadas en las respuestas JSON. Por supuesto, probablemente sea mejor si lo hacen por la cordura de todos. Sin embargo, si necesita utilizar propiedades personalizadas en los datos de respuesta, puede hacerlo. Veamos cómo funciona.
aplicación / Http / Resources / Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class Post extends JsonResource { public function toArray($request) { return [ 'the_custom_id' => $this->id, 'the_custom_title' => $this->title, 'the_custom_body' => $this->body ]; } } |
La respuesta JSON de la API ahora usa esas propiedades personalizadas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | { "data": [ { "the_custom_id": 1, "the_custom_title": "This Post Has Been Updated!", "the_custom_body": "Some fresh new updates for you." }, { "the_custom_id": 2, "the_custom_title": "Enim ut cupiditate dolorum quos enim.", "the_custom_body": "Mollitia sequi tempora cupiditate quia. Mollitia aliquid nesciunt provident. Nam reiciendis delectus a est repellendus omnis ut occaecati." }, { "the_custom_id": 3, "the_custom_title": "Nihil libero nam quisquam optio.", "the_custom_body": "Aut vitae ut deserunt beatae magnam eaque. Eaque quam rerum dolores ea tempore sint ipsa. Velit mollitia sapiente a. Et ratione quam soluta odit ullam fugit dolores voluptatum." }, { "the_custom_id": 4, "the_custom_title": "Quis esse a sit est.", "the_custom_body": "Corporis tempore autem optio odit atque sed. Cupiditate adipisci recusandae doloribus quas. Tempora qui sequi error rerum aperiam voluptas." }, { "the_custom_id": 6, "the_custom_title": "Eum soluta qui quas.", "the_custom_body": "Omnis dolor quos unde dolor. Quam ex non voluptates qui harum cumque soluta. Natus rerum deleniti eveniet ad." } ], "links": { "first": "http://lpgvue.io/api/posts?page=1", "last": "http://lpgvue.io/api/posts?page=5", "prev": null, "next": "http://lpgvue.io/api/posts?page=2" }, "meta": { "current_page": 1, "from": 1, "last_page": 5, "path": "http://lpgvue.io/api/posts", "per_page": 5, "to": 5, "total": 25 } } |
Devolver un solo recurso
Ahora veamos cómo devolver un solo recurso en el método show () de nuestro controlador.
aplicación / Http / Controllers / PostController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Http\Resources\Post as PostResource; class PostController extends Controller { public function index() { // Get the posts $posts = Post::paginate(5); // Return collection of posts as a resource return PostResource::collection($posts); } public function store(Request $request) { // } public function show($id) { // Get a single post $post = Post::findOrFail($id); // Return a single post as a resource return new PostResource($post); } public function destroy($id) { // } } |
Este es el resultado resultante al visitar http://lpgvue.io/api/post/5
| { "data": { "id": 5, "title": "Nam velit doloribus cumque qui cumque.", "body": "Voluptates culpa quidem omnis soluta animi eaque. Nihil voluptates voluptas quis cum adipisci tenetur. Eveniet voluptatem quo velit ea occaecati ducimus sed." } } |
Agregar datos adicionales
Para agregar algunos datos adicionales a las respuestas enviadas, como la versión api y otras cosas, puede configurar el método with () como lo hacemos aquí.
aplicación / Http / Resources / Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class Post extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'title' => $this->title, 'body' => $this->body ]; } public function with($request) { return [ 'version' => '1.0.0', 'api_url' => url('http://lpgvue/api') ]; } } |
Al visitar http://lpgvue.io/api/post/5
, ahora vemos esos metadatos adicionales en la respuesta. Entonces, podemos ver que esta es una forma realmente poderosa de personalizar exactamente lo que desea que produzca la API.
| { "data": { "id": 5, "title": "Nam velit doloribus cumque qui cumque.", "body": "Voluptates culpa quidem omnis soluta animi eaque. Nihil voluptates voluptas quis cum adipisci tenetur. Eveniet voluptatem quo velit ea occaecati ducimus sed." }, "version": "1.0.0", "api_url": "http://lpgvue/api" } |
Crear y actualizar
El mismo punto final se puede usar para actualizar una publicación o crear una nueva por completo. La única diferencia es el verbo HTTP que se utiliza al realizar la solicitud. Si se utiliza una solicitud PUT, se supone que se actualizará una publicación. Si se utiliza una solicitud POST, eso significa que se está creando una nueva publicación. El código aquí permite una actualización de Post o una creación de Post usando el mismo método store () en PostController.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Http\Resources\Post as PostResource; class PostController extends Controller { public function index() { // Get the posts $posts = Post::paginate(5); // Return collection of posts as a resource return PostResource::collection($posts); } public function store(Request $request) { // Allow for post update *or* create a new post $post = $request->isMethod('put') ? Post::findOrFail($request->id) : new Post; $post->id = $request->input('id'); $post->title = $request->input('title'); $post->body = $request->input('body'); if ($post->save()) { return new PostResource($post); } } public function show($id) { // Get a single post $post = Post::findOrFail($id); // Return a single post as a resource return new PostResource($post); } public function destroy($id) { // } } |
Prueba de una actualización posterior
Para probar una API cuando aún no tiene una interfaz formal construida, puede usar una gran herramienta como Postman. Probar con Postman nos permite enviar solicitudes de API a la aplicación utilizando el verbo HTTP de nuestra elección. Aquí configuraremos una solicitud PUT al http://lpgvue.io/api/post endpoint
. Esto nos permitirá actualizar una publicación. El primer paso es establecer el tipo de solicitud como PUT y agregar un encabezado a la solicitud para especificar el tipo de contenido de la aplicación / json.
El segundo paso es hacer clic en la pestaña Cuerpo, seleccionar sin procesar y agregar la carga útil json a la solicitud. Para actualizar una publicación, debemos especificar la identificación, el título y el cuerpo con los datos que se actualizarán.
El último paso es hacer clic en el botón Enviar y, si todo va bien, verá una respuesta con la publicación actualizada en la carga útil.
Prueba de una creación posterior
Ahora que estamos familiarizados con el flujo de trabajo básico en Postman, también deberíamos poder crear fácilmente una nueva publicación. Para hacer esto, podemos configurar una solicitud POST al mismo punto final http://lpgvue.io/api/post
que acabamos de usar en el ejemplo de actualización. Observe que configuramos la carga útil json para incluir un nuevo título y cuerpo para la publicación. No necesitamos incluir una identificación, ya que la aplicación asignará una nueva identificación automáticamente.
Cuando haces clic en Enviar, Postman disparará esa solicitud POST y deberías obtener una respuesta 201 Created con la publicación recién creada en el cuerpo de la respuesta.
Ver la tabla de publicaciones en nuestra base de datos directamente también muestra esa nueva publicación que se creó.
Eliminar un recurso
Para completar nuestra API y permitir la funcionalidad CRUD completa a través de JSON Rest Api, podemos agregar la capacidad de eliminar una publicación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Http\Resources\Post as PostResource; class PostController extends Controller { public function index() { // Get the posts $posts = Post::paginate(5); // Return collection of posts as a resource return PostResource::collection($posts); } public function store(Request $request) { // Allow for post update *or* create a new post $post = $request->isMethod('put') ? Post::findOrFail($request->id) : new Post; $post->id = $request->input('id'); $post->title = $request->input('title'); $post->body = $request->input('body'); if ($post->save()) { return new PostResource($post); } } public function show($id) { // Get a single post $post = Post::findOrFail($id); // Return a single post as a resource return new PostResource($post); } public function destroy($id) { // Get the post $post = Post::findOrFail($id); // Delete the post, return as confirmation if ($post->delete()) { return new PostResource($post); } } } |
Ahora, intentemos eliminar la publicación con la identificación de 5. La solicitud de eliminación es muy fácil. Todo lo que tiene que hacer es proporcionar el punto final para acceder, incluida la identificación, y presionar Enviar. Asegúrese de que el tipo de verbo HTTP esté configurado en DELETE.
Ahora, cuando visitemos http://lpgvue.io/api/posts
para ver todas las publicaciones, observe que aparecen en la lista en orden como 1, 2, 3, 4 y luego 6. Eso significa que nuestra eliminación de la ID de publicación 5 funcionó.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | { "data": [ { "id": 1, "title": "This Post Has Been Updated!", "body": "Some fresh new updates for you." }, { "id": 2, "title": "Enim ut cupiditate dolorum quos enim.", "body": "Mollitia sequi tempora cupiditate quia. Mollitia aliquid nesciunt provident. Nam reiciendis delectus a est repellendus omnis ut occaecati." }, { "id": 3, "title": "Nihil libero nam quisquam optio.", "body": "Aut vitae ut deserunt beatae magnam eaque. Eaque quam rerum dolores ea tempore sint ipsa. Velit mollitia sapiente a. Et ratione quam soluta odit ullam fugit dolores voluptatum." }, { "id": 4, "title": "Quis esse a sit est.", "body": "Corporis tempore autem optio odit atque sed. Cupiditate adipisci recusandae doloribus quas. Tempora qui sequi error rerum aperiam voluptas." }, { "id": 6, "title": "Eum soluta qui quas.", "body": "Omnis dolor quos unde dolor. Quam ex non voluptates qui harum cumque soluta. Natus rerum deleniti eveniet ad." } ], "links": { "first": "http://lpgvue.io/api/posts?page=1", "last": "http://lpgvue.io/api/posts?page=5", "prev": null, "next": "http://lpgvue.io/api/posts?page=2" }, "meta": { "current_page": 1, "from": 1, "last_page": 5, "path": "http://lpgvue.io/api/posts", "per_page": 5, "to": 5, "total": 25 } } |
Resumen del tutorial de recursos de la API de Laravel
En este tutorial, creamos una API JSON CRUD completa utilizando la función de recursos de la API de Laravel . Podemos ver que es realmente fácil configurar una API de backend usando Laravel y las muchas herramientas que nos brinda. A continuación, veremos cómo crear un Vue Front End que puede consumir nuestra API.
0 Comentarios