Eloquent es el ORM incluido en Laravel, pero puede usarse en cualquier proyecto PHP instalando el paquete illuminate/database. Ofrece una sintaxis fluida para definir modelos, relaciones y consultas sin necesidad del framework completo.
Instalación
composer require illuminate/database
Configurar Capsule Manager
Capsule es el punto de entrada de Eloquent fuera de Laravel:
<?php
require 'vendor/autoload.php';
use IlluminateDatabaseCapsuleManager as Capsule;
$capsule = new Capsule();
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'tienda',
'username' => 'root',
'password' => 'secret',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
?>
Definir un modelo
<?php
use IlluminateDatabaseEloquentModel;
class Producto extends Model
{
protected $table = 'productos';
protected $primaryKey = 'id';
public $timestamps = true; // created_at, updated_at
protected $fillable = ['nombre', 'precio', 'stock', 'categoria_id'];
protected $casts = [
'precio' => 'float',
'stock' => 'integer',
];
}
?>
CRUD básico
<?php
// Crear
$p = Producto::create(['nombre' => 'Teclado', 'precio' => 49.99, 'stock' => 10]);
// Leer
$p = Producto::find(1);
echo $p->nombre;
// Buscar con condición
$agotados = Producto::where('stock', 0)->get();
// Actualizar
Producto::where('id', 1)->update(['precio' => 44.99]);
// Eliminar
Producto::destroy(1);
?>
Relación hasMany
Un pedido tiene muchas líneas. En el modelo Pedido:
<?php
class Pedido extends Model
{
protected $fillable = ['cliente_id', 'total'];
public function lineas()
{
return $this->hasMany(LineaPedido::class, 'pedido_id');
}
}
?>
Uso:
<?php
$pedido = Pedido::with('lineas')->find(5);
foreach ($pedido->lineas as $linea) {
echo "{$linea->producto_nombre}: {$linea->cantidad}n";
}
?>
with('lineas') ejecuta un único JOIN en lugar de una query por línea (eager loading).
Relación belongsTo
Cada línea pertenece a un pedido:
<?php
class LineaPedido extends Model
{
protected $table = 'lineas_pedido';
protected $fillable = ['pedido_id', 'producto_id', 'cantidad', 'precio_unitario'];
public function pedido()
{
return $this->belongsTo(Pedido::class, 'pedido_id');
}
public function producto()
{
return $this->belongsTo(Producto::class, 'producto_id');
}
}
?>
Relación belongsToMany (tabla pivot)
Un producto pertenece a muchas categorías y viceversa:
<?php
class Producto extends Model
{
public function categorias()
{
return $this->belongsToMany(Categoria::class, 'producto_categoria', 'producto_id', 'categoria_id');
}
}
class Categoria extends Model
{
public function productos()
{
return $this->belongsToMany(Producto::class, 'producto_categoria');
}
}
// Sincronizar categorías de un producto
$producto->categorias()->sync([1, 3, 7]);
?>
Query Builder
Eloquent expone el Query Builder de Laravel cuando no necesitas un modelo completo:
<?php
use IlluminateDatabaseCapsuleManager as DB;
$resultados = DB::table('productos')
->select('nombre', 'precio')
->where('stock', '>', 0)
->orderBy('precio', 'asc')
->limit(10)
->get();
foreach ($resultados as $fila) {
echo "{$fila->nombre}: {$fila->precio}n";
}
?>
Migraciones sin Laravel
Capsule también puede crear tablas mediante el Schema Builder:
<?php
Capsule::schema()->create('productos', function ($table) {
$table->id();
$table->string('nombre');
$table->decimal('precio', 10, 2);
$table->unsignedInteger('stock')->default(0);
$table->foreignId('categoria_id')->constrained();
$table->timestamps();
});
?>
Errores comunes
- MassAssignmentException: los campos que quieres crear/actualizar masivamente deben estar en
$fillableo usar$guarded = []. - timestamps desactivados: si la tabla no tiene
created_at/updated_at, añadepublic $timestamps = false;. - Nombre de tabla automático: Eloquent infiere el nombre en plural inglés. Si tu tabla se llama diferente, declara
$table.
