CRUD Laravel usando Resources, Controllers, Models y Migrations

Crear un CRUD de Laravel generando código con artisan

Este es un tutorial que se basa en mi experiencia con Laravel. Te mostraré cómo crear un CRUD de cualquier entidad en pocos minutos, es decir, de manera muy rápida, usando:

  • Resources
  • Controllers
  • Models
  • Migrations

Todo esto usando artisan para generar el código. Verás que una vez que lo sepas, dejarás que artisan genere el código base.

Esto es un tip de productividad con Laravel.

¿Qué vamos a hacer?

Vamos a crear un CRUD simple de una entidad: nivel escolar. Es decir, un nivel de la escuela, como primario, secundario, etcétera. No es necesario que entiendas la entidad, sino sus datos, que son:

  • id
  • nombre
  • timestamps

¡Vamos allá!

Generando modelo y migración

Comenzamos generando nuestro modelo o entidad, además de una migración. Recuerda que una migración es una modificación que le haces a la estructura de la base de datos. Ejecutamos:

php artisan make:model Nivel -m

La opción -m es para crear la migración. Ahora se habrá creado el modelo en App\Nivel, y la migración en migrations.

Comencemos viendo el modelo, le vamos a definir las propiedades fillables y el nombre de la tabla:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Nivel extends Model
{
    protected $table = "niveles";
    protected $fillable = ["nombre",
    ];
}

Ya verás por qué llenamos los fillables más tarde. Ahora miremos la migración, le vamos a arreglar el nombre de la tabla de igual forma, y a definir las columnas:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateNivelsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('niveles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string("nombre");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('niveles');
    }
}

Es momento de hacer la migración:

php artisan migrate

Ahora en tu base de datos debe existir la tabla con las columnas:

MariaDB [sistema_escolar_2]> describe niveles;
+------------+---------------------+------+-----+---------+----------------+
| Field      | Type                | Null | Key | Default | Extra          |
+------------+---------------------+------+-----+---------+----------------+
| id         | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| nombre     | varchar(191)        | NO   |     | NULL    |                |
| created_at | timestamp           | YES  |     | NULL    |                |
| updated_at | timestamp           | YES  |     | NULL    |                |
+------------+---------------------+------+-----+---------+----------------+
4 rows in set (0.04 sec)

MariaDB [sistema_escolar_2]>

Ya tenemos lista la tabla y el modelo.

Crear controlador tipo resource

El modelo ya está definido, ahora vamos a definir el controlador, pero será un controlador de tipo resource; es decir, va a manejar las operaciones más básicas. Lo creamos con:

php artisan make:controller NivelesController --resource --model=Nivel

Con la opción --resource indicamos que será un controlador resource. La opción --model indica el modelo que usará o al que se referirá ese controlador.

Se debió crear un archivo algo así:

<?php

namespace App\Http\Controllers;

use App\Nivel;
use Illuminate\Http\Request;

class NivelesController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Nivel  $nivel
     * @return \Illuminate\Http\Response
     */
    public function show(Nivel $nivel)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Nivel  $nivel
     * @return \Illuminate\Http\Response
     */
    public function edit(Nivel $nivel)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Nivel  $nivel
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Nivel $nivel)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Nivel  $nivel
     * @return \Illuminate\Http\Response
     */
    public function destroy(Nivel $nivel)
    {
        //
    }
}

Registrar resource

El controlador ya está creado, pero todavía no está expuesto en las rutas. Dentro de las rutas web usamos:

<?php
use App\Http\Controllers\NivelesController;

Route::resource("niveles", NivelesController::class)->parameters(["niveles"=>"nivel"]);

Estamos especificando los parámetros por eso de plural y singular, pues en este caso Laravel pensará que el singular de “niveles” es “nivele”, cosa incorrecta; así que le indicamos que el singular de niveles es nivel.

Eso registrará todas las rutas de ese controlador y dará unos nombres que harán la programación más fácil, pues creará:

  • niveles.index
  • niveles.create
  • niveles.edit
  • etcétera

Es decir, le dará un nombre a cada ruta. Así, al hacer una redirección no debemos poner la ruta, sino que podemos poner simplemente su nombre.

CRUD

Ahora sí vamos a ver el CRUD en donde vamos a definir las vistas con formularios, tablas, etcétera. Yo usaré Bootstrap pero esto no tiene que ver mucho con el estilo, el punto es que entiendas el punto.

Las vistas irán dentro de una carpeta que tiene el mismo nombre que el modelo, es decir, habrá un directorio llamado niveles.

La nomenclatura que uso es:

  • modelo_edit.blade.php
  • modelo_index.blade.php
  • modelo_create.blade.php

En este caso “modelo” será niveles.

Create

Comenzamos con create. Definimos la vista:

@extends("maestra")
@section("titulo", "Registrar nivel")
@section("contenido")
    <div class="row">
        <div class="col-12">
            <form method="POST" action="{{route("niveles.store")}}">
                @csrf
                <div class="form-group">
                    <label class="label">Nombre</label>
                    <input required autocomplete="off" name="nombre" class="form-control"
                           type="text" placeholder="Nombre">
                </div>

                @include("notificacion")
                <button class="btn btn-success">Guardar</button>
                <a class="btn btn-primary" href="{{route("niveles.index")}}">Volver al listado</a>
            </form>
        </div>
    </div>
@endsection
Create
Create

Ahora dentro del controlador modificamos dos funciones. La primera es la que muestra la vista y se ve así:

<?php
/**
 * Show the form for creating a new resource.
 *
 * @return \Illuminate\Http\Response
 */
public function create()
{
    return view("niveles.niveles_create");
}

Más tarde, modificamos store, que es en donde el modelo se guarda dentro de la base de datos:

<?php
/**
 * Store a newly created resource in storage.
 *
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $nivel = new Nivel($request->input());
    $nivel->saveOrFail();
    return redirect()->route("niveles.index")->with(["mensaje" => "Nivel creado",
    ]);
}

¿Recuerdas las propiedades fillables? aquí las estamos usando

Presta atención a la línea en donde creamos un nuevo Nivel. Lo llenamos con $request->input(), es decir, llenamos sus propiedades directamente del formulario. Los fillables indican cuáles datos son “seguros” de llenar por el usuario de manera automática.

Read o index

Veamos ahora el index. Aquí es en donde se listan los niveles. Creamos la vista:

@extends("maestra")
@section("titulo", "Niveles")
@section("contenido")
    <div class="row">
        <div class="col-12">
            <a href="{{route("niveles.create")}}" class="btn btn-success mb-2">Agregar</a>
            @include("notificacion")
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>Nombre</th>

                    <th>Editar</th>
                    <th>Eliminar</th></tr>
                </thead>
                <tbody>
                @foreach($niveles as $nivel)
                    <tr>
                        <td>{{$nivel->nombre}}</td>
                        <td>
                            <a class="btn btn-warning" href="{{route("niveles.edit",[$nivel])}}">
                                <i class="fa fa-edit"></i>
                            </a>
                        </td>
                        <td>
                            <form action="{{route("niveles.destroy", [$nivel])}}" method="post">
                                @method("delete")
                                @csrf
                                <button type="submit" class="btn btn-danger">
                                    <i class="fa fa-trash"></i>
                                </button>
                            </form>
                        </td>
                    </tr>
                @endforeach
                </tbody>
            </table>

        </div>
    </div>
@endsection
Index - Mostrar modelos en Laravel
Index – Mostrar modelos en Laravel

Dentro del controlador regresamos la vista con los niveles usando Nivel::all() para traer todos los datos.

<?php
/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    return view("niveles.niveles_index", ["niveles"=>Nivel::all()]);
}

Al dibujar la tabla creamos algunos enlaces que llevarán a edit o delete.

Edit y update

De igual forma creamos la vista:

@extends("maestra")
@section("titulo", "Editar nivel")
@section("contenido")
    <div class="row">
        <div class="col-12">
            <form method="POST" action="{{route("niveles.update", [$nivel])}}">
                @method("PUT")
                @csrf
                <div class="form-group">
                    <label class="label">Nombre</label>
                    <input required value="{{$nivel->nombre}}" autocomplete="off" name="nombre" class="form-control"
                           type="text" placeholder="Nombre">
                </div>

                @include("notificacion")
                <button class="btn btn-success">Guardar</button>
                <a class="btn btn-primary" href="{{route("niveles.index")}}">Volver</a>
            </form>
        </div>
    </div>
@endsection

Por favor nota cómo es que definimos las rutas, el método y varias cosas aprovechando el resource; podemos pasar el modelo directamente.

Ahora vamos a ver el controlador, comenzando por mostrar la vista:

<?php
/**
 * Show the form for editing the specified resource.
 *
 * @param \App\Nivel $nivel
 * @return \Illuminate\Http\Response
 */
public function edit(Nivel $nivel)
{
    return view("niveles.niveles_edit", ["nivel" => $nivel,
    ]);
}

Se devuelve la vista del formulario, pero le pasamos el modelo para que rellene los datos. También vamos a preparar el método que actualiza al modelo en la base de datos:

<?php
/**
 * Update the specified resource in storage.
 *
 * @param \Illuminate\Http\Request $request
 * @param \App\Nivel $nivel
 * @return \Illuminate\Http\Response
 */
public function update(Request $request, Nivel $nivel)
{
    $nivel->fill($request->input())->saveOrFail();
    return redirect()->route("niveles.index")->with(["mensaje" => "Nivel actualizado"]);
}

Al invocar a fill, de nuevo llenamos o hidratamos al modelo con el formulario. Lo guardamos y volvemos al index.

Delete

Para terminar veamos cómo eliminar. Recuerda que la ruta del delete ya está al listar los elementos y es de hecho un formulario que se envía.

Lo que tenemos que hacer es, desde el controlador, eliminar al modelo. Queda así:

<?php
/**
 * Remove the specified resource from storage.
 *
 * @param \App\Nivel $nivel
 * @return \Illuminate\Http\Response
 */
public function destroy(Nivel $nivel)
{
    $nivel->delete();
    return redirect()->route("niveles.index")->with(["mensaje" => "Nivel eliminado",
    ]);
}

Debido a que ya tenemos el modelo como argumento en la función, y a su vez es un modelo de Eloquent, invocamos a delete y eso es todo.

Poniendo todo junto y probando CRUD

Eso es todo lo necesario. Ahora podemos probar.

CRUD Laravel usando Resources, Controllers, Models y Migrations
CRUD Laravel usando Resources, Controllers, Models y Migrations

Como puedes ver hemos creado un CRUD usando Laravel, generando código con artisan.

Te invito a leer más sobre Laravel en mi blog.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

2 comentarios en “Crear un CRUD de Laravel generando código con artisan”

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *