CRUD de Laravel con MySQL o MariaDB
Hoy toca el turno de Laravel (un framework de PHP) para conectarse a la base de datos más popular: MySQL.
En este post voy a explicar cómo conectar Laravel con MySQL o MariaDB, comenzando por configurar la base de datos, pasando a través de las rutas, repasando el motor de plantillas de Blade y tocando un poco el tema de los mensajes flash.
Al final vamos a tener un CRUD o ABC, en donde se verán las operaciones básicas de Laravel con MySQL: insert o insertar, update o actualizar, select o seleccionar y finalmente delete o eliminar.
Aviso
Este CRUD es muy básico y perfecto para los que se inician en Laravel, no creas que no le puse estilos o cosas bonitas por pereza, sino que lo hice lo más simple posible para no confundir al principiante con cosas que no tienen que ver con el motivo principal.
Si no sabes PHP o MySQL, o quieres repasar un poco, dejo unos links que te pueden ayudar:
- Comenzar a administrar MySQL desde la CLI
- Comenzar proyecto de Laravel
- Pasos a seguir después de clonar un proyecto de Laravel
- CRUD de PHP con MySQL sin frameworks
- Sistema de ventas con PHP y MySQL
- Ejercicios resueltos de MySQL
- Parte 2 de los ejercicios de MySQL
Descripción del proyecto
La razón por la que he escrito una serie de tutoriales de Laravel es porque el framework es un poco complicado de entender para explicar un simple CRUD con MySQL como el que hicimos con PHP puro.
Por ejemplo, para conectar Laravel con MySQL hay que configurar el archivo .env, establecer las rutas, definir las vistas y trabajar con modelos y migraciones.
Basta de presentaciones: haremos un CRUD de Laravel 5.8 (que debería funcionar perfectamente en otras versiones) con MySQL.
Si eres un principiante de Laravel igualmente puedes comenzar viendo este CRUD que traté de hacer lo más simple posible, aunque ahí están los enlaces a los otros posts por si te interesan.
Lo que vamos a hacer
Haremos un CRUD o ABC con Laravel y MySQL en donde registraremos canciones, las actualizaremos, eliminaremos y listaremos. Todo ello sin escribir una sola consulta SQL.
Recuerda que no veremos relaciones ni normalización, pues vamos a hacerlo lo más simple posible.
El código fuente está disponible en Github, por si vas no olvides seguirme.
Base de datos y tablas
La base de datos se llama canciones_laravel
. El esquema se ve así:
/*
Este esquema es por si no sabes manejar las migraciones
Recomiendo ver database/migrations
*/
create database canciones_laravel;
use canciones_laravel;
create table canciones(
id bigint unsigned not null auto_increment,
nombre varchar(100) not null,
artista varchar(100) not null,
album varchar(50) not null,
anio int unsigned not null,
primary key(id)
);
Recuerda que no es necesario que hagas la tabla, dejo el esquema para guiarte o como último recurso; de ahí basta con que ejecutes el comando php artisan migrate
para que las migraciones se ejecuten. De hecho la única migración es esta.
Nota: no te preocupes por las inyecciones SQL, si usas el ORM de Laravel o la fachada de DB
no hay problema.
Vistas con Blade
He definido una plantilla maestra y a partir de ella extiendo las demás. Pondré únicamente la maestra, pues las demás las puedes ver en el repositorio.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>@yield("titulo")</title>
<style>
/*
Poner bordes a las tablas. Tomado de:
Ejemplo de tabla en HTML con bordes CSS
*/
table {
border-collapse: collapse;
}
table,
th,
td {
border: 1px solid black;
}
th,
td {
padding: 5px;
}
</style>
</head>
<body>
<a href="{{route('inicio')}}">Inicio</a>
<a href="{{route('formAgregar')}}">Agregar</a>
@yield("contenido")
<hr>
<p>
CRUD de MySQL con Laravel. Creado por <a href="//parzibyte.me">parzibyte</a>
</p>
</body>
</html>
Pongo algunos estilos, el pie que va en común y permito cambiar el título por las vistas que son extendidas.
También tengo dos enlaces que son formados de acuerdo al nombre de las rutas que existen en web.php, las cuales veremos más abajo.
Mensajes flash
Para avisar que la canción fue eliminada, creada o actualizada utilizo los mensajes flash como se verá en el controlador. En Blade los muestro comprobando si hay un mensaje con session
.
@if(session("mensaje"))
<h3 style="color: blue;">{{ session("mensaje") }}</h3>
@endif
En el controlador se verá cómo se envían, pero como un adelanto diré que es con el método with
.
El modelo
Solamente vamos a trabajar con un modelo, el cual se llama Cancion. Lo generé con:
php artisan make:model Cancion
Aunque igual y se podía simplemente crear un archivo dentro de la carpeta app.
Su definición queda así:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Cancion extends Model
{
# Por defecto Laravel tomaría "cancion" así que mejor indicamos el nombre
protected $table = "canciones";
# No queremos que ponga updated_at ni created_at
public $timestamps = false;
}
Parece simple pero con él vamos a realizar el CRUD, pues al extender de Model tiene todos los métodos del ORM de Laravel. El punto es que hay dos propiedades:
- El nombre de la tabla, que no es necesario especificar pero si no lo hiciera, Laravel lo haría por mí con un nombre como “cancion”.
- Los timestamps establecidos en false. Esto es porque no queremos llevar un registro de cuándo se actualizó o eliminó un elemento.
Nota: si quieres que lleven esos dos campos, en tu migración llama a $table->timestamps();
El controlador de las canciones
El controlador es el que se encarga de pegar la vista y el modelo. Queda así (ábrelo en el repositorio si quieres):
<?php
namespace App\Http\Controllers;
/*
Si no sabes de dónde viene el nombre de las
tablas y en dónde estamos confugrando las credenciales
mira el archivo .env y database/esquema.sql
También echa un vistazo a las migraciones
*/
# Queremos acceder a la petición HTTP
use Illuminate\Http\Request;
# También queremos al modelo Cancion
use App\Cancion;
class CancionesController extends Controller
{
// Devolver la vista con todas las canciones
public function index()
{
$canciones = Cancion::get();
return view("inicio")
->with("canciones", $canciones);
}
public function agregarCancion(Request $peticion)
{
# Crear un modelo...
$cancion = new Cancion;
# Establecer propiedades leídas del formulario
$cancion->nombre = $peticion->nombre;
$cancion->artista = $peticion->artista;
$cancion->album = $peticion->album;
$cancion->anio = $peticion->anio;
# Y guardar modelo ;)
$cancion->save();
/*
Ahora redirige a la ruta con el nombre
inicio (mira routes/web.php) y pásale
un mensaje en la variable "mensaje" con
el valor de "Canción agregada"
*/
return redirect()
->route('inicio')
->with('mensaje', 'Canción agregada');
}
public function guardarCambiosDeCancion(Request $peticion)
{
# El id para el where de SQL
$idCancionQueSeActualiza = $peticion->idCancion;
# Obtener modelo fresco de la base de datos
# Buscar o fallar
$cancion = Cancion::findOrFail($idCancionQueSeActualiza);
# Los nuevos datos
$cancion->nombre = $peticion->nombre;
$cancion->artista = $peticion->artista;
$cancion->album = $peticion->album;
$cancion->anio = $peticion->anio;
# Y guardamos ;)
$cancion->save();
/*
Ahora redirige a la ruta con el nombre
inicio (mira routes/web.php) y pásale
un mensaje en la variable "mensaje" con
el valor de "Canción actualizada"
*/
return redirect()
->route('inicio')
->with('mensaje', 'Canción actualizada');
}
public function editarCancion(Request $peticion)
{
$idCancion = $peticion->route("id");
# Obtener canción por ID o fallar, es decir, mostrar un 404
$cancion = Cancion::findOrFail($idCancion);
return view("editar_cancion")
->with("cancion", $cancion);
}
public function eliminarCancion(Request $peticion)
{
# El id para el where de SQL
$idCancionQueSeElimina = $peticion->route("id");
# Obtener canción o mostrar 404
$cancion = Cancion::findOrFail($idCancionQueSeElimina);
# Eliminar
$cancion->delete();
/*
Ahora redirige a la ruta con el nombre
inicio (mira routes/web.php) y pásale
un mensaje en la variable "mensaje" con
el valor de "Canción eliminada"
*/
return redirect()
->route('inicio')
->with('mensaje', 'Canción eliminada');
}
}
La cosa importante que debemos notar es que usamos el modelo para todo, y que en ningún momento estamos escribiendo una consulta SQL; todo es a través del modelo.
Para eliminar llamamos a $cancion->delete()
, para guardar cambios o insertar una nueva llamamos a $cancion->save()
y finalmente para obtener todas las canciones a Cancion::get();
Un método que me gusta mucho es el de findOrFail
, el cual busca por id o falla; es decir, si no encuentra la canción muestra un error 404 en lugar de que intente eliminar u obtener un dato que no existe.
Antes de llamar a $cancion->save()
le ponemos todos sus datos con las propiedades mágicas. Es decir, cada columna de la base de datos se representa por una propiedad. Un ejemplo es cuando le ponemos el nombre:
$cancion->nombre = $peticion->nombre;
Para obtener los datos que se enviaron por el formulario accedemos a la variable $peticion
que es una instancia de Request, y Request trae de una forma cómoda lo que sea que haya sido enviado.
Finalmente en muchos casos redireccionamos a otras rutas con datos flash o flash data que muestran un mensaje de una sola vez.
Las rutas web
Ahora veamos el lugar en donde exponemos nuestra app: las rutas. Solamente fue cuestión de modificar el archivo web.php como vimos en el tutorial de rutas.
Puedes ver el archivo actualizado dentro del repositorio, y también dejo aquí el código:
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
/**
* Recomiendo:
* Rutas parte 1: https://parzibyte.me/blog/2019/02/14/explicando-rutas-web-laravel-5-7/
* Rutas parte 2: https://parzibyte.me/blog/2019/02/20/rutas-laravel-parte-2-prefijos-fallback-limite-de-tasa-formularios/
*/
# Cuando se solicita la url /, es decir, la raíz
Route::get('/', "CancionesController@index")
->name("inicio");
# Mostrar el formulario para agregar
Route::view("/agregar", "nueva_cancion")
->name("formAgregar");
# Cuando se envía el formulario y se debe guardar la canción
Route::post("/agregar", "CancionesController@agregarCancion")
->name("agregarCancion");
# Cuando se guardan los cambios en la base de datos
Route::post("/guardarCambios", "CancionesController@guardarCambiosDeCancion")
->name("guardarCambiosDeCancion");
# Mostrar el formulario para editar la canción, algo como editar/1
Route::get("/editar/{id}", "CancionesController@editarCancion")
->name("editarCancion");
# URL que es llamada para eliminar canción, algo como eliminar/1
Route::get("/eliminar/{id}", "CancionesController@eliminarCancion")
->name("eliminarCancion");
A cada ruta le pongo un nombre para luego crear un enlace en las vistas de Blade.
Poniendo todo junto
Con eso que configuramos y codificamos nuestra app ya está lista. Ahora basta con ir al sitio en donde lo tenemos alojado y podemos comenzar a probar. Aquí dejo un GIF de cómo se ve:
Recuerda que eres libre de descargar y probar por ti mismo el proyecto. Si tienes dudas déjalas en los comentarios.
¿Quieres aprender más de Laravel? haz click aquí.
Un codigo muy didactico, pero que pasa si la tabla de canciones ya llega a tener mas de un millon de registros, el aplicativo se volveria lento, que recomiendas frente a grandes manejos de informacion??
No entiendo por qué se volvería lento. Los motores de bases de datos están diseñados para manejar millones de datos. Si se refiere a que sería lento mostrar el millón de registros en una página web podría implementar una paginación: https://parzibyte.me/blog/2020/06/24/laravel-paginacion-registros/
Pingback: Laravel: subir archivos y aplicar validación - Parzibyte's blog