logo cosasdedevs
Cómo crear las acciones de CRUD en un API con Laravel 8. Parte 1 Modelos y creación

Cómo crear las acciones de CRUD en un API con Laravel 8. Parte 1 Modelos y creación



My Profile
Mar 24, 2021

¡Hola! Seguimos con la segunda parte de este tutorial para montar una API con Laravel 8. En esta segunda parte, veremos como crear la primera parte del CRUD, en la que nos encargaremos de crear las rutas para acceder a nuestra API, el controlador para gestionar nuestras acciones y añadiremos la primera acción que será de poder subir las fotos de nuestros perretes utilizando un token de autenticación como aprendimos en el tutorial anterior.

Antes de seguir, si no tienes muy claro el funcionamiento de una API, te dejo esta guía que escribí para entender su funcionamiento al 100%.

Guía para aprender a trabajar con APIs

Modelos

Para este caso vamos a crear un modelo llamado Post que guardará información sobre las fotos de nuestros perretes, un título y una descripción. Para ello lanzamos el siguiente comando:

php artisan make:model Post -m

Al añadir el parámetro -m, le estamos indicando que además del modelo queremos que cree el archivo de migración para la base de datos.

Una vez creado el modelo, vamos a la carpeta database/migrations y dentro debemos tener un nuevo archivo que como prefijo tendrá la fecha actual (fecha de la creación de la migración) más _create_posts_table.php. Este archivo contendrá la información para crear la tabla posts dentro de nuestra base de datos. Así que para añadir las columnas que necesitamos, lo abrimos y sustituimos el contenido del método up por el siguiente:

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained();
        $table->string('title');
        $table->string('image');
        $table->mediumText('description');
        $table->timestamps();
    });
}

Como comenté antes, añadimos los campos para guardar el título, la imagen y la descripción. También generamos la relación con la tabla de usuarios para saber de qué usuario es el post. El método id() creará el campo para la clave primaria y el método timestamps() genera dos campos para guardar la fecha de creación y la fecha de la última actualización.

Ahora debemos abrir el archivo app/Models/Post.php y dentro de la clase, añadiremos el siguiente código de tal forma que el archivo nos debería quedar así:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    /**
     * Get the user record associated with the post.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Con el método user podremos asociar un usuario con el post y podremos acceder a los datos del usuario cuando recorramos nuestros posts.

Por último, lanzamos el siguiente comando para crear la tabla en la base de datos:

php artisan migrate

CRUD

Ahora que ya tenemos el modelo, es hora de ponerse manos a la obra con el CRUD, así que lo primero que vamos a hacer es crear el controlador con el siguiente comando:

php artisan make:controller Api/V1/PostController --api --model=Post

Al igual que el controlador de autenticación, PostController será guardado dentro de la carpeta V1 para poder separar futuras versiones de la API. El parámetro --api creará automáticamente los métodos del CRUD y --model=Post le indicará que este controlador trabajará con los datos del modelo Post.

Ahora que ya tenemos el controlador, vamos a generar las rutas así que vamos al archivo routes/api.php y añadimos la siguiente línea:

Route::apiResource('v1/posts', App\Http\Controllers\Api\V1\PostController::class)->middleware('api');

Con esta simple línea crearemos todas las rutas con las que podremos acceder a los cinco métodos de PostController que podrán realizar las siguientes acciones: 

Mostrar un listado todas las fotos.

Mostrar una en concreto por el id.

Crearlas.

Actualizarlas

Eliminarlas.

Para ver las rutas generadas, podéis lanzar el siguiente comando:

php artisan route:list
+--------+-----------+---------------------+---------------+----------------------------------------------------+------------+
| Domain | Method    | URI                 | Name          | Action                                             | Middleware |
+--------+-----------+---------------------+---------------+----------------------------------------------------+------------+
|        | GET|HEAD  | /                   |               | Closure                                            | web        |
|        | POST      | api/v1/auth/login   | login         | App\Http\Controllers\Api\V1\AuthController@login   | api        |
|        | POST      | api/v1/auth/logout  | logout        | App\Http\Controllers\Api\V1\AuthController@logout  | api        |
|        |           |                     |               |                                                    | auth:api   |
|        | POST      | api/v1/auth/me      | me            | App\Http\Controllers\Api\V1\AuthController@me      | api        |
|        |           |                     |               |                                                    | auth:api   |
|        | POST      | api/v1/auth/refresh | refresh       | App\Http\Controllers\Api\V1\AuthController@refresh | api        |
|        |           |                     |               |                                                    | auth:api   |
|        | GET|HEAD  | api/v1/posts        | posts.index   | App\Http\Controllers\Api\V1\PostController@index   | api        |
|        | POST      | api/v1/posts        | posts.store   | App\Http\Controllers\Api\V1\PostController@store   | api        |
|        | GET|HEAD  | api/v1/posts/{post} | posts.show    | App\Http\Controllers\Api\V1\PostController@show    | api        |
|        | PUT|PATCH | api/v1/posts/{post} | posts.update  | App\Http\Controllers\Api\V1\PostController@update  | api        |
|        | DELETE    | api/v1/posts/{post} | posts.destroy | App\Http\Controllers\Api\V1\PostController@destroy | api        |
+--------+-----------+---------------------+---------------+----------------------------------------------------+------------+

Ahora tenemos las rutas, pero nos falta controlar que los endpoints para la creación, actualización y borrado necesiten de un usuario autenticado para poder utilizarlos. Para añadir este control, debemos ir al archivo app/Http/Controllers/Api/V1/PostController.php y en él crearemos el constructor de la clase en el que añadiremos el siguiente código:

public function __construct()
{
    $this->middleware('auth:api', ['except' => ['index', 'show']]);
}

Con esta línea le diremos a Laravel que a excepción de los métodos index y show los demás necesitarán pasar por el middleware auth:api, el cual se encargará de validar el token que pasemos por la cabecera.

Creación

Ahora que ya tenemos las rutas y el controlador es hora de darle vidilla a nuestra API. Para ello, lo primero que haremos será habilitar la funcionalidad para añadir nuevos posts para más adelante poder probar los endpoints para listar todos los post y el post por id.

Lo primero que vamos a hacer es crear una request. Esta funcionalidad la utilizaremos para validar los datos que nos envíe el usuario. Para crear la request lanzamos el siguiente comando:

php artisan make:request V1/PostRequest

Al lanzar este comando nos creará un archivo dentro de la ruta app/Http/Requests/V1/PostRequest.php. Pues bien, lo que vamos a hacer ahora es abrir ese archivo y sustituir su contenido por el siguiente:

<?php

namespace App\Http\Requests\V1;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;

class PostRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return Auth::check();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required|max:70',
            'image' => 'required|image|max:1024',
            'description' => 'required|max:2000',
        ];
    }
}

Este archivo tiene dos métodos, el primero, el método authorize que solo permitirá realizar la petición si el usuario está autenticado. Para ello utiliza el método check de la clase Auth que devuelve true si el usuario que realiza la petición si está autenticado y si no devolverá false. En caso de no estar autenticado retornará el error 401 unauthorized.

El segundo método es el método rules. En este método validaremos los datos que nos debe enviar el usuario que son el título, la imagen y la descripción. Como podéis ver, retorna un array con formato clave valor en el que cada clave es el campo a enviar y su valor son las distintas reglas que debe cumplir para ser validado separadas por |. Si no cumple alguna de estas reglas, Laravel devolverá un error.

Dicho esto vamos a explicar las reglas que vamos a utilizar:

La regla required indicará que el campo es obligatorio.

En title, max:70 indicará el número máximo de caracteres que podrá enviar un usuario para asignar un título.

En image, añadimos la regla image que indica que vamos a enviar un fichero de tipo imagen. En este caso, max:1024 indicará que el tamaño máximo de una imagen será de 1024KB.

En description al igual que en title añadimos la regla max esta vez con un límite de 2000 caracteres.

Aparte de estas hay muchas más reglas, para verlas podéis hacerlo pinchando en el siguiente enlace.

El siguiente paso que vamos a realizar es añadir la funcionalidad para poder crear post. Para ello abrimos el archivo app/Http/Controllers/Api/V1/PostController.php e importamos las clases PostRequest y Auth, aparte añadimos el siguiente código en el método store y creamos el método update que usaremos para guardar las imágenes.

<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
use App\Http\Requests\V1\PostRequest;
use Illuminate\Support\Facades\Auth;

class PostController extends Controller
{
...
    /**
     * Store a newly created resource in storage.
     *
     * @param  App\Http\Requests\V1\PostRequest $request
     * @return \Illuminate\Http\Response
     */
    public function store(PostRequest $request)
    {
        $request->validated();

        $user = Auth::user();

        $post = new Post();
        $post->user()->associate($user);
        $url_image = $this->upload($request->file('image'));
        $post->image = $url_image;
        $post->title = $request->input('title');
        $post->description = $request->input('description');

        $res = $post->save();

        if ($res) {
            return response()->json(['message' => 'Post create succesfully'], 201);
        }
        return response()->json(['message' => 'Error to create post'], 500);
    }

    private function upload($image)
    {
        $path_info = pathinfo($image->getClientOriginalName());
        $post_path = 'images/post';

        $rename = uniqid() . '.' . $path_info['extension'];
        $image->move(public_path() . "/$post_path", $rename);
        return "$post_path/$rename";
    }
...

Una vez hecho esto vamos a explicar que es lo que hace el método store.

Lo primero que hacemos es validar los datos que nos envía el usuario, para ello lanzamos el método validated() del objeto $request y este comprobará que se cumplen las reglas que creamos en la clase PostRequest.

El siguiente paso es obtener el usuario y crear un objeto de tipo post guardar la información. Asociamos el usuario al post y nos valemos del método upload para guardar la imagen en la carpeta pública de Laravel y nos retornará su url, de esta forma podremos guardar su ruta en la bbdd y visualizarla más adelante.

Añadimos también el título y la descripción y usamos el método save del objeto $post para guardar los cambios. Si todo ha ido bien retornará true y enviaremos al usuario un mensaje diciendo que todo ha ido bien, si no, le diremos al usuario que hemos tenido un error y nos tocará revisar 🤷‍♂️.

Ahora que ya lo tenemos montado es hora de probarlo. Como el tutorial anterior yo utilizaré Postman, pero podéis utilizar la herramienta que más os guste.

Primero deberemos generar el token para poder autenticarnos. Si estáis usando Postman y queréis ver como poder automatizar el guardado del token os dejo este tutorial en el que lo explico paso a paso.

Una vez hecho esto lanzaremos una petición a la siguiente url http://localhost:8000/api/v1/posts. Esta petición deberá ser de tipo post y en ella deberemos enviar los parámetros title, image y description. También tenemos que enviar las siguientes cabeceras para que funcione correctamente:

Content-type: multipart/form-data;
Authorization: Bearer <my-token>
Accept: application/json

Si todo ha ido bien debería mostraros algo como esto:

Y esto es todo por esta primera parte de este tutorial, en cuanto tenga el siguiente pondré el enlace por aquí 😁.

Como siempre os dejo el enlace al proyecto.

Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.

Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.

Nos leemos 👋.

26843 vistas

🐍 Sígueme en Twitter

Si te gusta el contenido que subo y no quieres perderte nada, sígueme en Twitter y te avisaré cada vez que cree contenido nuevo 💪
Luego ¡Te sigo!

Nos tomamos en serio tu privacidad

Utilizamos cookies propias y de terceros para recopilar y analizar datos sobre la interacción de los usuarios con cosasdedevs.com. Ver política de cookies.