Los problemas de exactitud y consistencia de los datos pueden dar lugar a todo tipo de problemas, desde pequeños inconvenientes hasta grandes problemas corporativos. Es fundamental crear un código que almacene, modifique y borre de forma segura los datos de tu base de datos.
Entra en las transacciones de la base de datos de Laravel.
Las transacciones de base de datos son un enfoque eficaz para garantizar la integridad de los datos. Laravel simplifica estas transacciones en una amplia gama de bases de datos.
Pero, ¿qué son exactamente? ¿Cómo puedes realizarlas en Laravel?
Al final de esta extensa guía, habrás aprendido todo sobre las transacciones de base de datos en Laravel y cómo utilizarlas eficazmente en tu proyecto.
¿Qué Son las Transacciones de Base de Datos en Laravel?
Antes de entrar en la parte técnica, vamos a entender primero qué son las transacciones de base de datos de Laravel y cómo puedes beneficiarte de ellas.
Una transacción de base de datos es un conjunto de operaciones que puedes realizar de forma segura dentro de la estructura de la base de datos de tu aplicación, como consultas SQL para modificar datos (por ejemplo, actualizaciones, eliminaciones e inserciones).
En cualquier momento, puedes decidir deshacer todas las consultas de la transacción. Además, todas las consultas que realices serán tratadas como una única acción por la base de datos.
Veamos un ejemplo de esto.
Supongamos que tenemos una aplicación que permite a los usuarios crear cuentas. Naturalmente, puede haber uno o varios usuarios asociados a cada cuenta. Si esta aplicación genera simultáneamente una cuenta y el primer usuario, tendrás que resolver lo que ocurre si una cuenta se genera correctamente, pero el usuario no.
Echa un vistazo a este código de ejemplo:
// Create Account
$newAcct = Account::create([
'accountname' => Input::get('accountname'),
]);
// Create User
$newUser = User::create([
'username' => Input::get('username'),
'account_id' => $newAcct->id,
]);
Aquí hay dos escenarios que pueden causar problemas desagradables:
- La cuenta no se genera
- Fallo en la creación de un usuario
Consideremos la última situación.
Tener una cuenta sin usuarios disponibles conduce a la inconsistencia de los datos en la base de datos. Para solucionarlo, puedes optar por la desalentadora tarea de programar para evitarlo o ahorrarte mucho código o simplemente empaquetarlo en una transacción para hacer las cosas rápidamente.
Aunque las transacciones de base de datos están presentes en la mayoría de las bases de datos SQL, varían principalmente en su implementación y eficiencia. Los sistemas más populares, como MySQL, SQLite, PostgreSQL y Oracle, admiten transacciones, por lo que no deberías tener problemas para implantar tu base de datos SQL preferida.
Migraciones
La migración es una funcionalidad crucial en Laravel que te permite crear una tabla en tu base de datos, hacer modificaciones y compartir el esquema de la base de datos de la aplicación. Puedes utilizar la migración de Laravel para editar tablas añadiendo nuevas columnas o eliminando las existentes.
Imaginemos que estás discutiendo ideas con un equipo y necesitas hacer ajustes en la tabla. El archivo SQL debe ser compartido e importado por alguien del equipo. Es posible que se olviden de importar el archivo SQL, causando problemas en el funcionamiento de la aplicación.
Aquí es donde la migración de Laravel viene al rescate. Puedes añadir una nueva columna a tu base de datos o eliminar entradas sin afectar a las que ya están ahí.
Sembradores
El sembrado es una herramienta proporcionada por Laravel para que los desarrolladores puedan facilitar la prueba de diferentes tipos de datos, corregir errores y ajustar el rendimiento. Puedes añadir múltiples filas de datos ficticios automáticamente a tu tabla de base de datos a través del sembrado de la base de datos en un solo comando.
Como resultado, puedes empezar de nuevo con una nueva base de datos y valores de muestra en lugar de tener que introducirlos manualmente cada vez que se restaura la base de datos.
Opciones para las Transacciones de la Base de Datos de Laravel
Laravel ofrece diferentes herramientas como Adminer para gestionar tus datos. Para las transacciones de la base de datos, hay tres métodos en la parte de la base de datos para iniciar una transacción manualmente y tener un control total sobre la gestión de las transacciones.
Muchos usuarios encuentran estas opciones más flexibles para definir exactamente cuándo se debe confirmar o revertir una transacción:
- Crea una transacción: Utiliza el comando
DB::beginTransaction();
para iniciar una transacción. - Deshacer una transacción: Utiliza el comando
DB::rollBack();
si quieres realizar cambios o deshacer acciones. - Confirmar una transacción: Si todo ha ido según lo previsto, utiliza el comando
DB::commit();
.
Recuerda siempre concluir cada transacción abierta con una acción de consignación o de reversión, especialmente los bucles. De lo contrario, este método manual se desincronizará y tus registros no se actualizarán.
Cómo Trabajar con tu Base de Datos Laravel
Las migraciones y los seeders, como se ha mencionado anteriormente, son soluciones sofisticadas diseñadas para que los desarrolladores de Laravel puedan desplegar, eliminar y restaurar rápidamente la base de datos de una aplicación reduciendo las disparidades. Resulta muy útil, especialmente cuando más de un desarrollador trabaja en la misma aplicación.
Esta sección te mostrará cómo utilizar fácilmente las migraciones y los seeders con tu base de datos de Laravel utilizando los comandos de artisan.
Requisitos Previos
Esto es lo que necesitas para empezar:
- Un usuario no root con permisos sudo en un ordenador local de Ubuntu 18.04 o en un servidor de desarrollo. Es una buena idea tener configurado un cortafuegos activo si utilizas un servidor remoto.
- LEMP instalado en tu máquina. Puedes optar por instalar Docker y Docker Compose para ejecutar tu aplicación si te sientes más cómodo trabajando con ellos.
Nuestra herramienta DevKinsta está impulsada por Docker y es utilizada por 60,000++ desarrolladores y diseñadores para crear y desarrollar fácilmente sitios de WordPress individuales o múltiples.
Hay otras herramientas de desarrollo web que puedes utilizar en función de tus habilidades y necesidades de codificación.
Migraciones de Laravel
Hay dos métodos en una categoría de migración: de subida y de bajada. El método de subida se utiliza para crear nuevas tablas, índices o columnas en la base de datos. El método de bajada debe deshacer los efectos del método de subida.
Puedes utilizar el constructor de esquemas de Laravel para construir y editar tablas libremente en cada uno de estos métodos. Por ejemplo, esta migración genera una tabla de vuelos:
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateFlightsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
Schema::create('flights', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
Schema::drop('flights');
}
Ten en cuenta que los comandos make:migration
necesitan aclarar el nombre de la tabla. Así que asegúrate de que el table_name
coincide con lo que quieres.
Puedes utilizar las opciones --table
y --create
para especificar el nombre de la tabla y si la migración creará una nueva tabla, como se muestra a continuación:
php artisan make:migration create_users_table --create=users
php artisan make:migration add_votes_to_users_table --table=users
Tu directorio database/migrations incluirá ahora la nueva migración. El nombre de cada archivo de migración incluye una marca de tiempo, que Laravel utiliza para determinar el orden de la migración.
También tienes la opción de definir un --path
, que debe estar relacionado con el directorio root de tu instalación. Utiliza el siguiente comando:
php artisan migrate:make foo --path=app/migrations
Ejecutar Migraciones
Hay algunos comandos útiles que puedes aprovechar al ejecutar migraciones. Vamos a repasar algunos de ellos:
php artisan migrate
: Este comando publica todo tu esquema en la base de datos. También genera una tabla en la base de datos.php artisan migrate --path=app/foo/migrations
: Este comando ejecuta todas las migraciones bajo un directorio. Si recibes un mensaje de error «No hay nada que migrar», ejecuta el comandophp artisan migrate --path=database/migrations/foo
sin el directorio de la aplicación.php artisan migrate --package=vendor/package
: Utiliza este comando si quieres ejecutar las migraciones de un paquete.
A veces puedes obtener un error «Clase no encontrada» al ejecutar migraciones. Si te ocurre, ejecuta el comando composer dump-autoload
.
Algunas migraciones pueden ser peligrosas y pueden provocar la pérdida de tus datos. Por ello, Laravel te pedirá que confirmes la ejecución de los comandos para salvaguardar tus datos.
Si no quieres que te pregunte, utiliza --force flag
para forzar los comandos de la siguiente manera:
php artisan migrate --force
Deshacer las Migraciones
Utiliza el comando de retroceso cuando necesites revertir el último lote de migraciones de la siguiente manera:
php artisan migrate:rollback
Aquí tienes otros comandos de retroceso que puedes utilizar:
php artisan migrate:reset
: Este comando revierte todas las migraciones, no sólo la última operación.php artisan migrate:fresh
: Utiliza este comando cuando quieras una nueva instalación de tu base de datos. Elimina todas las tablas existentes y ejecuta el comandomigration
.php artisan migrate:refresh
: Este es un comando dos en uno que ejecuta los dos comandos:rollback and migrate
.php artisan migrate:fresh --seed
: Esto ejecuta el comandomigrate:fresh
antes de sembrar la base de datos. Cuando instales la aplicación en un nuevo host, puedes utilizar este comando para sembrar (es decir, cargar datos en) la base de datos.
Seeders de Laravel
Un seeder (Alimentador o Sembrador) es una clase que crea y coloca muestras de datos (semillas) en una base de datos. Laravel proporciona una técnica sencilla para sembrar tu base de datos con datos de prueba utilizando clases sembradoras en el directorio database/seeds.
Eres libre de elegir el nombre de tus clases semilla. Pero te aconsejamos que sigas un patrón de nomenclatura claro de tu elección, como UsersTableSeeder. Después, se creará por defecto una clase DatabaseSeeder
para ti.
Aquí tienes un ejemplo de clase semilla de base de datos en Laravel:
class DatabaseSeeder extends Seeder {
public function run() {
$this->call('UserTableSeeder');
$this->command->info('User table seeded!');
}
}
class UserTableSeeder extends Seeder {
public function run() {
DB::table('users')->delete();
User::create(array('email' => '[email protected]'));
}
}
Creación de un Seeder (Sembrador)
Generar sembradores es muy fácil. Podrías hacerlo con los ojos cerrados (pero, por favor, no lo hagas).
Ejecuta el comando make:seeder
artisan para crear un sembrador. Ahora el directorio database/seeds incluirá todos los sembradores producidos por el marco:
php artisan make:seeder UsersTableSeeder
El método por defecto de una clase de sembrador es ejecutar. El proceso tiene lugar cuando aplicas el comando db:seed
artisan. Puedes introducir los datos en tu base de datos de la forma que prefieras utilizando la función de ejecución. Además, es perfectamente posible utilizar Eloquent model factories o Query Builder para insertar datos manualmente.
En cualquier caso, debes tener en cuenta que durante la introducción de datos en la base de datos, la protección de la asignación masiva se desactiva automáticamente.
En este caso, haremos modificaciones en la clase básica DatabaseSeeder
y añadiremos una sentencia de inserción en la base de datos al método de ejecución:
<?php
use IlluminateDatabaseSeeder;
use IlluminateSupportFacadesDB;
use IlluminateSupportFacadesHash;
use IlluminateSupportStr;
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* @return void
*/
public function run() {
DB::table('users')->insert([
'name' => Str::random(10),
'email' => Str::random(10).'@gmail.com',
'password' => Hash::make('password'),
]);
}
}
Si quieres escribir alguna dependencia dentro del código del método de ejecución, el contenedor de servicios de Laravel la resolverá automáticamente.
Además, puedes utilizar la función call
para ejecutar diferentes clases de siembra desde esta clase, lo que te permite personalizar el orden de siembra. Puedes dividir la siembra de tu base de datos en diferentes archivos, asegurando que ninguna clase sembradora se expanda excesivamente.
Introduce el nombre de la clase sembradora que quieras utilizar, como se muestra a continuación:
/**
* Run the database seeds.
*
* @return void
*/
public function run() {
$this->call([
UsersTableSeeder::class,
PostsTableSeeder::class,
CommentsTableSeeder::class,
]);
}
Ejecutar Seeders (Sembradoras)
Después de generar tu sembradora, es posible que tengas que utilizar el comando dump-autoload
para volver a crear el autocargador de Composer:
composer dump-autoload
A continuación, debes ejecutar el comando db:seed
artisan para sembrar tu base de datos:
php artisan db:seed
Este comando ejecuta la clase DatabaseSeeder
por delegación, que puede utilizarse para ejecutar otras clases sembradoras. Sin embargo, puedes utilizar el parámetro --class
para ejecutar una clase sembradora concreta por separado, como se indica a continuación:
php artisan db:seed --class=UserTableSeeder
¿Y si quieres volver a crear tu base de datos desde cero, incluyendo la eliminación de todas las tablas y la ejecución de todas las migraciones una vez más? En este caso, utiliza el comando migrate:fresh
para sembrar tu base de datos.
php artisan migrate:fresh --seed
Como ocurre con las migraciones, algunos procesos de sembrado pueden provocar pérdidas de datos o cambios no deseados. Por esta razón, se te pedirá la aprobación antes de ejecutar los sembradores para protegerte de la ejecución de comandos de sembrado en tu base de datos principal.
Si estás lo suficientemente seguro y no quieres que te interrumpa ese paso de seguridad, utiliza la bandera --force
que aparece a continuación:
php artisan db:seed --force
5 Formas Más De Usar Consultas De Base De Datos Raw en Laravel
Aunque Laravel proporciona herramientas útiles como Eloquent y Query Builder, todavía puedes realizar consultas raw utilizando SQL. Hemos reunido cinco formas diferentes de hacerlo.
Pero antes de empezar, debes saber que las consultas raw no están aseguradas automáticamente, lo que las convierte en un enfoque arriesgado. Por lo tanto, si vas a dar algún parámetro a la consulta, asegúrate de que está en el formato correcto y tiene los valores adecuados, como un número en lugar de un texto.
Cálculos de Media/Suma/Conteo
Puedes utilizar una consulta sin procesar si quieres crear GROUP BY ()
, y luego utilizar las funciones de agregación de MySQL como Count()
, SUM()
, AVG()
, MIN()
o MAX()
como se muestra en el siguiente ejemplo:
$users = DB::table('users')
->selectRaw('count(*) as user_count, status')
->where('status', '<>', 1)
->groupBy('status')
->get();
Incluso es posible hacer tanto count()
como avg()
en la misma consulta SQL:
$salaries = DB::table('salaries')
->selectRaw('companies.name as company_name, avg(salary) as avg_salary, count(*) as people_count')
->join('companies', 'salaries.company_id', '=', 'companies.id')
->groupBy('companies.id')
->orderByDesc('avg_salary')
->get();
Filtrar Años
Si necesitas realizar cálculos SQL dentro de GROUP BY
o ORDER BY
, puedes utilizar las consultas groupByRaw()
y orderByRaw()
. Después de la agrupación, también puedes utilizar la sentencia where
utilizando una consulta SQL having
con havingRaw ()
.
Por ejemplo, este comando de abajo muestra cómo agrupar un campo de fecha/hora por año:
$results = User::selectRaw('YEAR(birth_date) as year, COUNT(id) as amount')
->groupByRaw('YEAR(birth_date)')
->havingRaw('YEAR(birth_date) > 2000')
->orderByRaw('YEAR(birth_date)')
->get();
Calcular Un Solo Campo (Subconsulta)
Supón que quieres calcular una columna a partir de otra y devolver el resultado en una consulta SQL. ¿Cómo puedes hacerlo?
Echemos un vistazo:
$products = Product::select('id', 'name')
->selectRaw('price - discount_price AS discount')
->get();
Aquí tienes otro ejemplo de declaración SQL CASE
:
$users = DB::table('users')
->select('name', 'surname')
->selectRaw("(CASE WHEN (gender = 1) THEN 'M' ELSE 'F' END) as gender_text")
->get();
Convertir SQL Antiguo
Es muy común tener una sentencia SQL que requiera ser convertida a Eloquent o Query Builder, especialmente de un antiguo proyecto en el que se haya trabajado.
Pues bien, en realidad no necesitas hacer eso. En su lugar, puedes utilizar simplemente la sentencia DB::select()
como se muestra:
$results = DB::select('select * from users where id=?', [1]);
Ejecutar Consulta Sin Resultados
DB::statement
puede ejecutar una consulta SQL, sin obtener resultados como INSERT
o UPDATE
sin variables.
Esto se utiliza con frecuencia en la migración de bases de datos cuando cambia la estructura de una tabla y hay que cambiar los datos antiguos por los nuevos:
DB::statement('UPDATE users SET role_id = 1 WHERE role_id IS NULL AND YEAR(created_at) > 2020');
Además, DB::statement()
puede ejecutar cualquier consulta SQL con un esquema que no esté limitado a valores o columnas. Aquí tienes un ejemplo:
DB::statement('DROP TABLE users');
DB::statement('ALTER TABLE projects AUTO_INCREMENT=123');
Resumen
A estas alturas, deberías tener un conocimiento profundo de las transacciones de base de datos en Laravel y de cómo implementarlas. No sólo ayudan a la integridad de los datos, sino que también ayudan a optimizar el rendimiento de Laravel y facilitan tu proceso de desarrollo.