Domina las relaciones de Eloquent en Laravel con una guía clara y práctica. Aquí verás cómo modelar productos, categorías y usuarios, crear migraciones con claves foráneas, ajustar factories y validar el flujo con tests. Todo con un enfoque directo y listo para aplicar.
¿Cómo conectar productos, categorías y usuarios con Eloquent?
Para mapear la lógica del dominio, Eloquent permite declarar relaciones expresivas. Un producto pertenece a una categoría y una categoría tiene muchos productos. Además, un producto tiene un único usuario creador mediante el campo created_by.
¿Cómo declarar belongsTo y hasMany en los modelos?
En Product: relación con Category usando belongsTo.
En Category: relación inversa con hasMany.
En Product y User: relación created_by con belongsTo y hasMany.
Eloquent: ORM de Laravel para mapear tablas a modelos.
belongsTo / hasMany: relaciones 1:N expresivas y legibles.
created_by: campo que enlaza producto con su creador.
Integridad referencial: la foreign key en base de datos refuerza la relación.
¿Qué migraciones y claves foráneas necesitas en Laravel?
Primero, agrega category_id a products con un valor por defecto. Se crea una categoría “otros” y se usa su ID como default. Luego, define la foreign key y aplica un rollback para regenerarla correctamente.
// database/migrations/xxxx_xx_xx_add_category_id_to_products_table.phpreturnnewclassextendsMigration{publicfunctionup():void{// Crear categoría por defecto$defaultId=DB::table('categories')->insertGetId(['name'=>'otros','created_at'=>now(),'updated_at'=>now(),]);Schema::table('products',function(Blueprint$table)use($defaultId){$table->unsignedBigInteger('category_id')->default($defaultId);// Clave foránea recomendada para integridad de datos$table->foreign('category_id')->references('id')->on('categories');});}publicfunctiondown():void{Schema::table('products',function(Blueprint$table){$table->dropColumn('category_id');});}};
Aplicación de migraciones y rollback para regenerar la foreign key:
php artisan migrate:rollback
php artisan migrate
¿Cómo añadir created_by y vincular usuarios?
Se agrega la columna created_by a products con un usuario “administrador” por defecto, creado con el factory de User.
// database/migrations/xxxx_xx_xx_add_created_by_to_products_table.phpreturnnewclassextendsMigration{publicfunctionup():void{// Crear usuario por defecto: administrador$adminId=User::factory()->create(['name'=>'administrador'])->id;Schema::table('products',function(Blueprint$table)use($adminId){$table->unsignedBigInteger('created_by')->default($adminId);});}publicfunctiondown():void{Schema::table('products',function(Blueprint$table){$table->dropColumn('created_by');});}};
¿Cómo probar y sembrar datos con factories y seeders?
El testing valida las relaciones y evita errores comunes, como olvidar el return en un método de relación. Las factories generan datos realistas; los seeders controlan el orden en que se crean.
¿Cómo ajustar tests para belongsTo category?
Crear Category y Product con category_id asignado.
Afirmar que $product->category no sea nulo y coincida el ID.
¿Te gustaría ver más ejemplos de relaciones en Eloquent o resolver un caso específico de tu proyecto? Comparte tus dudas y cuéntame qué modelo quieres conectar a continuación.
Manejo de relaciones en bases de datos con Laravel
Primero no es necesario crear un modelo dentro de una clase de migración, para eso tenemos los factories, un factory permite retornar un array con los valores que corresponden a las columnas pasando como valor de la category el factory de la clase category, esto si la data es para desarrollo
Si la idea es tener un valor por defecto siempre, los modelos de eloquent proveen ya un metodo withDefault(), en el cual tambie retorna un array con la columna y el valor por defecto que esta tendría.
crear un modelo dentro de la migración en si no es malo solo hay estándares que permiten a todos entender que al setear un valor por defecto en un modelo es algo que corresponde al dominio del modelo y cualquier desarrollador buscaria en el modelo y no en las migraciones.
la migración AddCategoryIdToProductsTable es para ya no alterar la migración ya existente de products y asi evitar borrar datos, corríjanme si me equivoco.
¡Hola!, así es, internamente Laravel crea una tabla en tu base de datos llamada: migrations
Esta tabla tiene una columna llamada batch, ese es el lote en el cual la migración fue ejecutada, cada vez que ejecutas php artisan migrate y hay nuevas migraciones, ese batch aumenta, al hacer rollback, lo que hace Laravel es eliminar únicamente el último batch, y lo hace mediante el método down que definimos en los archivos de migración :D
para asociar un producto con una categoria en el factory, hice lo siguiente 'category_id'=>random_int(1, 15), obviamente en el seeder las categorias deberian generarse primero
"Declarar la clave foránea no es necesario dentro de Eloquent". Pues parece que sí ya que sin declararla no me dejaba hacerla migración y ya después de hacerla sí.
Hola, al probar mi EndPoint noto que me trae el ID de la categoría pero no hace la relacion con la tabla, investigando un poco mas veo que el problema es porque al crear la tabla Categories, le dejo de fabrica el ID, y al relacionar hago esto:
Por otro lado, el withDefault nos ofrece poder implementar el patron ** Null Object**, que para este caso no aplicaria, porque cada Producto tiene que tener una Categoria, debido a que es NOT NULL.
Gracias por el aporte!
Si alguien desea testear la relacion del producto con el usuario por medio de la relacion createdBy: