Laravel relaciones uno a muchos (One to Many)
Imagen de rawpixel.com en Freepik

En este tutorial aprenderás paso a paso cómo crear relaciones «uno a muchos» (One to Many) en Laravel y es que este tipo de relaciones son una manera de establecer una conexión entre dos modelos de datos (un modelo representa una tabla en la base de datos), en donde un registro de un modelo está relacionado con muchos registros de otro modelo, también aprenderás cómo poblar las tablas con datos falsos y probar las relaciones con la herramienta Tinker. Al final encontrarás el repositorio del tutorial. Sin más, manos a la obra.

Requisitos previos

  1.  Contar con un entorno de desarrollo como XAMPP, Wamp o Laragon.
  2.  Para este tutorial necesitas tener creado un proyecto en Laravel con una conexión a una base de datos.
  3.  Editor de textos como VS Code.

Planteamiento

Pondré como ejemplo un sistema de gestión de inventarios que cuenta con dos modelos Producto y Categoría en donde un producto pertenece a una categoría y una categoría puede tener varios productos. Para este ejemplo aplica la relación de «uno a muchos». Para implementar las relaciones «uno a muchos» (One to Many) en Laravel sigue estos pasos:

1. Crear modelos y migraciones

Como mencioné anteriormente para este ejemplo crearé dos modelos: Producto y Categoría con sus respectivas migraciones para ello abre una terminal de comandos en la raíz de tu proyecto en Laravel y primero crea el modelo Category ejecutando la instrucción:

php artisan make:model Category -m

Ahora para crear el modelo Product con su migración ejecuta:

php artisan make:model Product -m

NOTA. Es importante que los archivos de las migraciones se creen en este orden ya que de otra manera al correr las migraciones arrojará un error.

2. Configurar archivo de migraciones

Con tu editor de textos abre el archivo database/migrations/…create_categories_table.php y agrega el campo «name» para que quede así:

Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->timestamps();
});

Abre el archivo database/migrations/…create_products_table.php y agrega los siguientes campos:

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->text('description')->nullable();
    $table->float('price');
    $table->unsignedBigInteger('category_id')->nullable();
    $table->foreign('category_id')->references('id')->on('categories')->onDelete('set null');
    $table->timestamps();
});

En el código anterior hay dos métodos clave para definir la relación entre la tabla categories con la tabla products y son unsignedBigInteger y foreign. Con unsignedBigInteger se asigna al campo category_id un tipo de dato entero, positivo y puede ser un valor muy grande. Con foreign se define la llave foránea y la relación entre el campo category_id de la tabla products y el campo id de la tabla categories.

3. Relacionar los modelos Product y Category

Ahora toca crear las relaciones entre Product y Category a nivel de modelo usando Eloquent, abre el archivo app/Models/Category.php y como una categoría tiene muchos productos se debe usar el método en plural y se debe utilizar hasMany(). Agrega el código a tu archivo:

public function products(){
    return $this->hasMany(Product::class);
}

Abre el archivo app/Models/Product.php y como un producto pertenece a una sola categoría el método debe estar es singular y se debe utilizar belongsTo() para crear la relación inversa como lo muestra el siguiente código:

public function category(){
    return $this->belongsTo(Category::class);
}

4. Agregar datos de prueba

Para poblar la base de datos con información falsa de prueba se puede realizar haciendo uso de Factories o si quieres ingresar información preestablecida puedes generar Seeders, para este tutorial usaré Factories. En la terminal de comandos ejecuta la instrucción:

php artisan make:factory CategoryFactory

Y para crear el Factory del Model Product ejecuta:

php artisan make:factory ProductFactory

4.1 Configurar CategoryFactory

Abre el archivo database/factories/CategoryFactory.php y para agregar nombres de categorías falsos de prueba usarás la librería de Laravel Faker, dentro del método definition y dentro del array return agrega el siguiente código:

'name' => $this->faker->sentence(2)

4.2 Configurar ProductFactory

En el archivo database/factories/ProductFactory.php copia y pega este código que hará que la tabla products se poble de datos falsos de prueba:

<?php

namespace Database\Factories;

use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Product>
 */
class ProductFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        $category = Category::all()->random();
        return [
            'name' => $this->faker->sentence(2),
            'description' => $this->faker->text(),
            'price' => $this->faker->randomElement([9.99,25.99,99.99]),
            'category_id' => $category->id,
        ];
    }
}

4.3 Configurar archivo DatabaseSeeder

Abre el archivo database/seeders/DatabaseSeeder.php dentro del método run() agrega estas dos líneas de código que lo que hacen es generar el contenido de prueba:

Category::factory(5)->create();
Product::factory(25)->create();

NOTA. Recuerda importar los modelos Product y Category al inicio del archivo DatabaseSeeder.php y también recuerda haber creado una base de datos y estar conectado a ella configurando los datos de acceso en el archivo .env. Corre las migraciones y los factories ejecutando el comando:

php artisan migrate:fresh --seed

Si abres tu cliente de gestión de base de datos como PHPMyAdmin, Heidi o MySQL Workbench y verás que las tablas products y categories se han poblado con datos de prueba y están manteniendo la relación de uno a muchos entre ellas.

5. Probar las relaciones uno a muchos (One to Many) en Laravel

Laravel tiene integrada una poderosa herramienta de desarrollo llamada Tinker con la que puedes realizar consultas de prueba a las tablas relacionadas en la base de datos, para llamar a Tinker desde la terminal ejecuta el comando:

php artisan tinker

En la consola de Tinker puedes verificar si las relaciones se hicieron correctamente. Para trabajar con el modelo Product escribe aunque esta instrucción es opcional es buena práctica usarla:

use App\Models\Product

En Tinker puedes usar las instrucciones de Eloquent que normalmente utilizas en los controladores para hacer consultas a la base de datos. Por ejemplo para pedir la información del artículo cuyo ID es 5 solo ejecuta la instrucción:

$product = Product::find(5);

Te retornará toda la información del producto y se verá algo parecido a esta imagen:

Se muestran los datos del producto con id 5

Puedes ver que se muestra la columna category_id que está relacionada al id de la tabla categories, para ver el nombre de la categoría a la que pertenece este producto ejecuta la instrucción:

$product->category->name

Aquí puedes ver que las tablas están relacionadas correctamente. Ahora para probar las categorías primero tienes que declarar el Modelo que quieres usar:

use App\Models\Category

Si quieres ver todas las categorías que están guardadas en la tabla solo ejecuta la instrucción de Eloquent:

Category::all();

Para consultar una categoría en específico solo agrega a la consulta el id:

$category = Category::find(4)

Y ahora puedes consultar todos los productos que están relacionados a esta categoría para ello usa el método products, ejecuta:

$category->products

Las relaciones de las tablas a nivel base de datos y a nivel Modelos están funcionando correctamente.

Conclusión

En este tutorial aprendiste qué son y cómo implementar las relaciones uno a muchos (One to Many) en Laravel. Si ha sido de ayuda te invito a compartirlo en tus redes sociales para llegar a más personas y si tienes dudas o comentarios déjalos en la caja de comentarios estaré al pendiente de ellos. Saludos.

Referencias:
Laravel docs.
Repositorio de este tutorial.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.