Laravel
Tutorial Laravel: Bases de datos y Eloquent ORM
Aprende a usar Eloquent ORM para persistencia en aplicaciones web PHP con bases de datos SQL y almacenar modelos persistentes.
Aprende Laravel GRATIS y certifícateConfiguración de la base de datos
Para aprovechar al máximo el framework Laravel, es imprescindible configurar correctamente la conexión a la base de datos. Laravel simplifica este proceso mediante el uso de archivos de configuración y variables de entorno, lo que facilita la gestión de diferentes entornos como desarrollo, pruebas y producción.
Archivo .env
El archivo .env
ubicado en la raíz del proyecto contiene las variables de entorno que definen la configuración específica de cada entorno. Para configurar la base de datos, es necesario editar las siguientes líneas:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nombre_base_datos
DB_USERNAME=usuario
DB_PASSWORD=contraseña
- DB_CONNECTION: especifica el controlador de base de datos a utilizar, como
mysql
,pgsql
,sqlite
osqlsrv
. - DB_HOST: define la dirección IP o el nombre del host del servidor de base de datos.
- DB_PORT: indica el puerto por el cual se establece la conexión (por defecto,
3306
para MySQL). - DB_DATABASE: nombre de la base de datos a la que se conectará Laravel.
- DB_USERNAME y DB_PASSWORD: credenciales de acceso a la base de datos.
Es fundamental mantener estas credenciales seguras y no compartir el archivo .env
públicamente. Las variables de entorno permiten cambiar la configuración sin modificar el código fuente, lo que mejora la seguridad y la flexibilidad de la aplicación.
Archivo de configuración config/database.php
El archivo config/database.php
contiene la configuración global de las conexiones a bases de datos en Laravel. Aunque el archivo referencia a las variables de entorno, es importante revisarlo para comprender cómo Laravel gestiona las conexiones:
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'nombre_base_datos'),
'username' => env('DB_USERNAME', 'usuario'),
'password' => env('DB_PASSWORD', 'contraseña'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
// Otras opciones...
],
// Otras conexiones...
],
- La opción
default
determina la conexión por defecto que utilizará la aplicación. - En el arreglo
connections
, se definen las diferentes conexiones de base de datos disponibles. - Cada conexión utiliza las variables de entorno para mantener la configuración dinámica y segura.
Configuración para diferentes bases de datos
Laravel es compatible con múltiples sistemas de gestión de bases de datos. A continuación, se muestran ejemplos de configuración para algunos de ellos.
MySQL
Ya se ha mostrado la configuración básica para MySQL. Asegúrese de que el servicio de MySQL esté en ejecución y que el usuario tenga los permisos adecuados.
PostgreSQL
Para configurar PostgreSQL, ajuste las variables en el archivo .env
:
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=nombre_base_datos
DB_USERNAME=usuario
DB_PASSWORD=contraseña
Y modifique la conexión correspondiente en config/database.php
:
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'nombre_base_datos'),
'username' => env('DB_USERNAME', 'usuario'),
'password' => env('DB_PASSWORD', 'contraseña'),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
],
SQLite
SQLite es ideal para entornos de desarrollo y pruebas debido a su simplicidad. Para utilizar SQLite:
- Cree un archivo de base de datos en el directorio
database
:
touch database/database.sqlite
- Actualice el archivo
.env
:
DB_CONNECTION=sqlite
DB_DATABASE=/ruta/al/proyecto/database/database.sqlite
- En
config/database.php
, asegúrese de que la conexión SQLite esté configurada:
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DATABASE_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
Pruebas y migraciones
Una vez configurada la base de datos, es recomendable ejecutar las migraciones para crear las tablas necesarias:
php artisan migrate
Este comando utiliza las migraciones definidas en el directorio database/migrations
para crear la estructura de la base de datos. Si la configuración es correcta, verá mensajes indicando que las migraciones se han ejecutado con éxito.
Ejecución del servidor de desarrollo
Para verificar que la aplicación funciona correctamente con la base de datos, ejecute el servidor de desarrollo integrado de PHP desde la carpeta principal del proyecto:
php -S localhost:8000 -t public
Esto iniciará el servidor en http://localhost:8000
. Al acceder, Laravel debería mostrar la página de bienvenida o la interfaz definida en sus rutas y controladores.
Uso de variables de entorno adicionales
En casos donde se necesiten múltiples conexiones o configuraciones avanzadas, puede definir variables de entorno adicionales, como:
DB_READ_HOST=127.0.0.1
DB_READ_USERNAME=usuario_read
DB_READ_PASSWORD=contraseña_read
Y configurar las conexiones en config/database.php
utilizando dichas variables. Esto es útil para implementar estrategias de replicación o separar lecturas y escrituras.
La correcta configuración de la base de datos es esencial para el funcionamiento de una aplicación Laravel. Utilizar variables de entorno y mantener las credenciales fuera del código fuente mejora la seguridad y facilita la gestión de diferentes entornos. Asegúrese siempre de proteger el archivo .env
y de no incluirlo en el control de versiones.
Introducción a Eloquent ORM
El Eloquent ORM es el mapeador objeto-relacional que Laravel incorpora para facilitar la interacción con bases de datos de forma orientada a objetos. Eloquent proporciona una capa de abstracción que permite trabajar con las tablas y registros de la base de datos como si fueran clases y objetos en PHP, simplificando así las operaciones CRUD (Crear, Leer, Actualizar y Eliminar).
Con Eloquent, no es necesario escribir consultas SQL manualmente, ya que ofrece una sintaxis elegante y fluida para construir las consultas mediante métodos de PHP. Esto mejora la legibilidad y el mantenimiento del código, haciendo que las interacciones con la base de datos sean más intuitivas para los desarrolladores.
Una de las ventajas más destacadas de Eloquent es su capacidad para manejar las relaciones entre modelos de manera sencilla. Soporta relaciones uno a uno, uno a muchos, muchos a muchos, entre otras, y permite acceder y manipular los datos relacionados utilizando métodos y propiedades definidas en los modelos.
Eloquent sigue una serie de convenciones por defecto que facilitan su uso. Por ejemplo, asume que cada tabla de la base de datos tiene una clave primaria llamada id
y que el nombre del modelo en plural corresponde al nombre de la tabla. Estas convenciones pueden ser personalizadas si la estructura de la base de datos no sigue estos estándares.
Además, Eloquent incluye características avanzadas como eventos, observadores, scopes y mutadores, que permiten extender su funcionalidad y adaptarla a las necesidades específicas de cada proyecto. También facilita la serialización de modelos a formatos como JSON, lo cual es útil para la creación de APIs y servicios web.
La integración de Eloquent con el resto de componentes de Laravel es muy estrecha. Por ejemplo, se puede combinar con migraciones para gestionar la estructura de la base de datos y con seeders para poblarla con datos de prueba. Asimismo, al utilizar Eloquent junto con Blade y las vistas, es posible pasar directamente los modelos a las plantillas para renderizar los datos de forma eficiente.
Definición y uso de modelos
En Laravel, un modelo es una clase que representa una tabla de la base de datos y proporciona una interfaz para interactuar con los datos de esa tabla. Los modelos sirven como una capa intermedia entre la base de datos y la lógica de la aplicación, permitiendo trabajar con datos de forma orientada a objetos y utilizando las funcionalidades del Eloquent ORM.
Creación de un modelo
Para crear un modelo, se utiliza el comando artisan make:model
. Por ejemplo, para crear un modelo llamado Usuario
, se ejecuta en la terminal:
php artisan make:model Usuario
Este comando genera un archivo Usuario.php
dentro del directorio app/Models
. Por convención, los nombres de los modelos están en singular y en mayúscula inicial, mientras que las tablas correspondientes en la base de datos están en plural y en minúsculas.
Estructura básica de un modelo
El modelo generado extiende la clase base Illuminate\Database\Eloquent\Model
, heredando todas las funcionalidades del Eloquent ORM:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Usuario extends Model
{
//
}
Aquí, el espacio de nombres App\Models
indica la ubicación del modelo dentro del proyecto.
Configuración de atributos
Los modelos de Eloquent permiten configurar propiedades para adaptarse a las características de la tabla en la base de datos:
- $table: especifica el nombre de la tabla si difiere del nombre convencional.
protected $table = 'usuarios_custom';
- $primaryKey: define la clave primaria si es distinta de
id
.
protected $primaryKey = 'usuario_id';
- $incrementing: indica si la clave primaria es autoincremental.
public $incrementing = false;
- $keyType: establece el tipo de dato de la clave primaria.
protected $keyType = 'string';
- $timestamps: habilita o deshabilita el manejo automático de
created_at
yupdated_at
.
public $timestamps = false;
Asignación masiva y seguridad
Para proteger la aplicación de vulnerabilidades como el Mass Assignment, se utilizan las propiedades $fillable
y $guarded
:
- $fillable: lista de atributos que pueden ser asignados masivamente.
protected $fillable = ['nombre', 'email', 'password'];
- $guarded: lista de atributos que no pueden ser asignados masivamente.
protected $guarded = ['is_admin'];
Es recomendable usar $fillable
para especificar explícitamente qué campos son seguros para la asignación masiva.
Operaciones básicas con el modelo
Una vez definido el modelo, es posible realizar operaciones CRUD de manera sencilla.
- Crear un nuevo registro:
$usuario = new Usuario();
$usuario->nombre = 'Juan Pérez';
$usuario->email = 'juan@example.com';
$usuario->password = bcrypt('secreto');
$usuario->save();
- Asignación masiva al crear:
$datos = [
'nombre' => 'María López',
'email' => 'maria@example.com',
'password' => bcrypt('secreto'),
];
$usuario = Usuario::create($datos);
- Leer registros:
$usuarios = Usuario::all();
$usuario = Usuario::find(1);
$usuario = Usuario::where('email', 'juan@example.com')->first();
- Actualizar un registro:
$usuario = Usuario::find(1);
$usuario->nombre = 'Juan P.';
$usuario->save();
- Actualizar con asignación masiva:
$usuario->update(['nombre' => 'Juan Pérez García']);
- Eliminar un registro:
$usuario = Usuario::find(1);
$usuario->delete();
Uso de métodos estáticos
Eloquent proporciona métodos estáticos que simplifican las consultas:
- Obtener todos los registros:
$usuarios = Usuario::all();
- Búsqueda por clave primaria:
$usuario = Usuario::find($id);
- Condiciones en consultas:
$usuariosActivos = Usuario::where('activo', true)->get();
Personalización de consultas
Los modelos permiten definir scopes y utilizar métodos para personalizar las consultas:
- Scope local:
public function scopeActivos($query)
{
return $query->where('activo', true);
}
// Uso:
$usuarios = Usuario::activos()->get();
- Ordenamiento y limitación:
$usuarios = Usuario::orderBy('nombre', 'asc')->take(10)->get();
Cast de atributos y formatos
Para convertir automáticamente los atributos a tipos específicos, se utiliza la propiedad $casts
:
protected $casts = [
'email_verified_at' => 'datetime',
'activo' => 'boolean',
];
Esto asegura que al acceder a email_verified_at, se obtenga una instancia de Carbon para manejar fechas.
Eventos y hooks del modelo
Eloquent dispone de eventos que permiten ejecutar código en momentos específicos del ciclo de vida del modelo:
- Creando un registro:
protected static function booted()
{
static::creating(function ($usuario) {
$usuario->token = Str::random(32);
});
}
Este ejemplo genera un token aleatorio antes de crear un usuario.
Relación con controladores y vistas
En un controlador, se usa el modelo para interactuar con los datos y pasar información a las vistas:
public function index()
{
$usuarios = Usuario::all();
return view('usuarios.index', ['usuarios' => $usuarios]);
}
En una vista Blade, se accede a las propiedades del modelo:
@foreach($usuarios as $usuario)
<p>{{ $usuario->nombre }} - {{ $usuario->email }}</p>
@endforeach
Prácticas recomendadas
- Validación: siempre validar los datos antes de guardarlos en el modelo.
- Eager Loading: usar cargado ansioso para evitar consultas innecesarias.
$usuarios = Usuario::with('perfil')->get();
- Mantenimiento: mantener los modelos enfocados en la interacción con la base de datos y mover la lógica de negocio a servicios o helpers.
Consultas básicas con Eloquent
Eloquent ORM ofrece una interfaz expresiva y sencilla para realizar consultas en la base de datos. Permite construir consultas de manera fluida, combinando métodos que representan criterios y operaciones comunes en SQL. A continuación, se detallan las operaciones básicas de consulta que se pueden realizar con Eloquent.
Para ilustrar los ejemplos, consideraremos el modelo Usuario
previamente definido.
Recuperación de todos los registros
Para obtener todos los registros de una tabla, se utiliza el método estático all()
del modelo:
$usuarios = Usuario::all();
El resultado es una colección de instancias del modelo Usuario
, que se puede iterar y manipular como un array.
Uso de cláusulas where
Las condiciones se establecen mediante el método where()
, que recibe el nombre del campo, el operador y el valor:
$usuariosActivos = Usuario::where('activo', '=', true)->get();
Si el operador es =
, se puede omitir, simplificando la expresión:
$usuariosActivos = Usuario::where('activo', true)->get();
Es posible encadenar múltiples cláusulas where()
para añadir más condiciones:
$usuariosFiltrados = Usuario::where('activo', true)
->where('edad', '>', 18)
->get();
Cláusulas orWhere
Para agregar condiciones OR, se utiliza el método orWhere()
:
$usuarios = Usuario::where('rol', 'admin')
->orWhere('rol', 'editor')
->get();
Este ejemplo obtiene usuarios cuyo rol sea admin o editor.
Condiciones avanzadas
Eloquent proporciona métodos para condiciones más complejas:
whereIn()
: selecciona registros donde el valor de un campo está en una lista dada.
$usuarios = Usuario::whereIn('id', [1, 2, 3])->get();
whereBetween()
: selecciona registros donde el valor de un campo está entre dos valores.
$usuarios = Usuario::whereBetween('edad', [18, 30])->get();
whereNull()
ywhereNotNull()
: filtra registros con campos nulos o no nulos.
$usuariosSinTelefono = Usuario::whereNull('telefono')->get();
whereDate()
,whereMonth()
,whereYear()
: filtran por componentes de fecha.
$usuariosRecientes = Usuario::whereYear('created_at', date('Y'))->get();
Agrupación de condiciones
Para agrupar condiciones y definir la precedencia lógica, se utiliza una función anónima dentro de where()
:
$usuarios = Usuario::where('activo', true)
->where(function ($query) {
$query->where('rol', 'admin')
->orWhere('rol', 'editor');
})
->get();
De este modo, se obtienen usuarios activos que sean admin o editor.
Selección de columnas específicas
Por defecto, Eloquent recupera todas las columnas. Para seleccionar columnas específicas, se usa el método select()
:
$nombres = Usuario::select('nombre', 'email')->get();
Esto es útil para mejorar el rendimiento y obtener únicamente los datos necesarios.
Ordenamiento de resultados
Para ordenar los resultados, se utiliza orderBy()
:
$usuarios = Usuario::orderBy('nombre', 'asc')->get();
También se puede encadenar para múltiples criterios de orden:
$usuarios = Usuario::orderBy('apellido', 'asc')
->orderBy('nombre', 'asc')
->get();
Limitación y desplazamiento
Para limitar la cantidad de registros y establecer un desplazamiento, se usan take()
y skip()
, o sus alias limit()
y offset()
:
$usuarios = Usuario::skip(10)->take(5)->get();
Este ejemplo obtiene 5 usuarios, saltando los primeros 10.
Paginación
Eloquent facilita la paginación mediante el método paginate()
:
$usuarios = Usuario::orderBy('id', 'desc')->paginate(15);
Esto devuelve una colección de 15 usuarios por página, incluyendo información para crear links de paginación.
Uso de agregaciones
Para realizar operaciones de agregación, existen métodos como count()
, max()
, min()
, avg()
y sum()
:
- Contar registros:
$totalUsuarios = Usuario::count();
- Máximo valor de un campo:
$edadMaxima = Usuario::max('edad');
- Promedio de un campo:
$edadPromedio = Usuario::avg('edad');
Consultas crudas
Aunque Eloquent cubre la mayoría de necesidades, en ocasiones es necesario realizar consultas SQL crudas con DB::raw()
:
use Illuminate\Support\Facades\DB;
$usuarios = Usuario::select(DB::raw('COUNT(*) as total'), 'rol')
->groupBy('rol')
->get();
En este ejemplo, se cuentan usuarios agrupados por rol.
Conversión a array y JSON
Los resultados de las consultas pueden convertirse fácilmente a array o JSON:
- Convertir a array:
$usuariosArray = Usuario::all()->toArray();
- Convertir a JSON:
$usuariosJson = Usuario::all()->toJson();
Esto es útil para enviar datos a la vista o a través de una API.
Uso de modelos en las vistas
Al pasar los datos a las vistas, se pueden utilizar directamente en las plantillas Blade:
return view('usuarios.lista', ['usuarios' => $usuarios]);
En la vista, se recorre la colección:
@foreach($usuarios as $usuario)
<p>{{ $usuario->nombre }} - {{ $usuario->email }}</p>
@endforeach
Métodos adicionales de consulta
Eloquent incluye una variedad de métodos que permiten construir consultas de manera flexible:
first()
: obtiene el primer registro que coincide con la consulta.
$usuario = Usuario::where('email', 'juan@example.com')->first();
findOrFail()
: busca por clave primaria y lanza una excepción si no encuentra el registro.
$usuario = Usuario::findOrFail($id);
firstOrCreate()
: obtiene el primer registro que coincide o lo crea si no existe.
$usuario = Usuario::firstOrCreate(
['email' => 'juan@example.com'],
['nombre' => 'Juan Pérez', 'password' => bcrypt('secreto')]
);
updateOrCreate()
: actualiza un registro existente o lo crea con los datos proporcionados.
$usuario = Usuario::updateOrCreate(
['email' => 'juan@example.com'],
['nombre' => 'Juan P.', 'activo' => true]
);
Comparaciones avanzadas
Para operadores más allá del =
, se pueden utilizar otros dentro de where()
:
$usuarios = Usuario::where('edad', '>=', 18)->get();
También es posible utilizar whereColumn()
para comparar dos columnas:
$usuarios = Usuario::whereColumn('created_at', '>', 'updated_at')->get();
Uso de scopes
Los scopes locales permiten encapsular condiciones reutilizables en el modelo:
public function scopeAdultos($query)
{
return $query->where('edad', '>=', 18);
}
// Uso:
$usuariosAdultos = Usuario::adultos()->get();
Esto mejora la claridad y la reutilización del código.
Ejemplos prácticos
- Obtener usuarios cuyo nombre comience con una letra específica:
$usuarios = Usuario::where('nombre', 'like', 'A%')->get();
- Obtener los 5 usuarios más recientes:
$usuariosRecientes = Usuario::orderBy('created_at', 'desc')
->take(5)
->get();
- Contar usuarios por rol:
$conteoRoles = Usuario::select('rol', DB::raw('COUNT(*) as total'))
->groupBy('rol')
->get();
Consideraciones sobre rendimiento
- Eager Loading: para evitar el problema conocido como n+1 consultas, se utilizan las relaciones con
with()
:
$usuarios = Usuario::with('perfil')->get();
- Chunking: para procesar grandes cantidades de registros sin cargar todo en memoria:
Usuario::chunk(100, function ($usuarios) {
foreach ($usuarios as $usuario) {
// Procesar cada usuario
}
});
Depuración de consultas
Para visualizar la consulta SQL generada, se puede utilizar el método toSql()
:
$sql = Usuario::where('activo', true)->toSql();
// Muestra: "select * from `usuarios` where `activo` = ?"
Esto es útil para depurar y entender cómo Eloquent construye las consultas.
Todas las lecciones de Laravel
Accede a todas las lecciones de Laravel y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Php Laravel
Introducción Y Entorno
Instalación Y Configuración Laravel
Introducción Y Entorno
Controladores Mvc
Controladores Http
Vistas Y Blade Templates
Controladores Http
Formularios Y Validación
Controladores Http
Controladores Rest
Controladores Http
Middleware Y Control De Solicitudes
Persistencia
Seguridad Autenticación Y Autorización
Persistencia
Bases De Datos Y Eloquent Orm
Persistencia
Relaciones Entre Modelos
Persistencia
Consultas Avanzadas
Persistencia
Colecciones Y Métodos Avanzados
Persistencia
Migraciones Y Seeders
Persistencia
Sistema De Autenticación Nativo Laravel
Middlewares Y Seguridad
Autorización (Policies Y Gates)
Middlewares Y Seguridad
Csrf Y Protección De Formularios En Blade
Middlewares Y Seguridad
Validaciones De Datos En Controladores Y Formularios
Middlewares Y Seguridad
Cifrado De Contraseñas
Middlewares Y Seguridad
Autenticación Jwt En Api Rest
Middlewares Y Seguridad
Pruebas Unitarias Con Phpunit
Testing
Pruebas De Integración En Laravel
Testing
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la importancia de una adecuada configuración de la base de datos en Laravel.
- Establecer conexiones seguras usando el archivo
.env
. - Gestionar conexiones múltiples y diferentes tipos de bases de datos (MySQL, PostgreSQL, SQLite).
- Realizar pruebas y migraciones de bases de datos de manera efectiva.
- Utilizar variables de entorno para adaptar configuraciones según el entorno.
- Proteger credenciales y datos sensibles en archivos de configuración.