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
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
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.
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.
Hola. Dónde encuentro el archivo store.php. Saludos
En aprender Laravel
Este tutorial es claro y fácil de entender, gracias por compartirlo.