HasMany-uno a muchos-One to Many

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.



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:

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

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.

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.

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.

model categoria: Como una categoria tiene mucho produtos (hasMany-tiene muchas).

public function products(){     /*método en plural

    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 en singular y se debe utilizar belongsTo() para crear la relación inversa como lo muestra el siguiente código:

app/Models/Product.php

public function category(){

/*En singular producto pertenece a una sola categoría belongsTo-pertenece a

    return $this->belongsTo(Category::class);

}

 Agregar datos de prueba

https://documentacionlaravel.com/docs/9.x/eloquent-factories

https://laravel.com/docs/10.x/eloquent-factories

https://laravel.com/docs/10.x/seeding

De forma predeterminada, DatabaseSeederse define una clase para usted. Desde esta clase, puede usar el call método para ejecutar otras clases de inicialización, lo que le permite controlar el orden de inicialización.

Una clase seeder solo contiene un método por defecto: run. Este método se llama cuando se ejecuta el db:seed comando Artisan . Dentro del runmétodo, puede insertar datos en su base de datos como desee. Puede usar el generador de consultas para insertar datos manualmente o puede usar fábricas de modelos Eloquent .
 ingresar información preestablecida::
  public function run(): void
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }
Por supuesto, especificar manualmente los atributos para cada semilla del modelo es engorroso. En su lugar, puede usar 

public function run(): void
{
    User::factory()
            ->count(50)
            ->hasPosts(1)
            ->create();
}
Llamar a Seeders adicionales

El uso del callmétodo le permite dividir la inicialización de su base de datos en varios archivos para que ninguna clase única de inicialización sea demasiado grande. El callmétodo acepta una matriz de clases de sembrador que deben ejecutarse:

public function run(): void
{
    $this->call([
        UserSeeder::class,
        PostSeeder::class,
        CommentSeeder::class,
    ]);
}
Factories en Laravel
Con los Seeders que nos proporciona Laravel ya podemos llenar la tablas de nuestra base de datos. Sin embargo, es limitado ya que si queremos llenar más de 10, 100 registros sería prácticamente un ejerció en sufrimiento. Porque se crea una variable por cada registro de la tabla.

Por esta razón Laravel cuenta con los Factories que es otro forma de llenar los datos de una forma más automatizada, y generar gran cantidad de datos.

Los Factories son sencillos de utilizar, solo se debe especificar en cada campo de la tabla que tipo de dato se quiere llenar, posteriormente la cantidad de registros que se quiere generar en la tabla.

Generar un Model Factory

Los Seeders por otra parte son archivos que nos van a permitir poblar nuestra base de datos para no tener que perder el tiempo escribiendo de forma manual todos los datos.

php artisan make:seeder CategoryFactory

php artisan make:seeder ProductFactory

$factory->define(\App\Profession::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence
    ];

Con esto ya tenemos el archivo pero no es todo lo que necesitamos para poder trabajar con datos autogenerados, para ello usaremos un componente llamado Faker el cual se encargará de generar estos datos. 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:

Crear los factorys

php artisan make:factory CategoryFactory

Y para crear el Factory del Model Product ejecuta:

php artisan make:factory ProductFactory

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)

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:

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,

        ];

    }

}

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.

 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:



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.

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.

===================================================================

 HasMany

Varias publicaciones están escritas por un Author, por lo que el Author HasMany (tiene muchas) publicaciones. En esta relación, la tabla de publicaciones tiene un campo author_id que contiene la clave externa de la tabla de autores.

En el modelo Author, la relación se define así:


public function posts(): HasMany
{
return $this->hasMany(Post::class);
}

La conexión de una publicación con un autor se puede hacer así:
$author->posts()->save($post);

Laravel actualizará el campo posts.author_id con la identificación del autor.

Cuando la relación está configurada correctamente, puede recuperar una colección de publicaciones como esta:

$author->posts

Cuando llame al método de relación, obtendrá un objeto HasMany que también es un generador (de consultas).


// Collection of published Post models related to

 $author.$author->posts()->where('published', true)->get();


bibliografia::

https://blog.pleets.org/article/relacion-uno-a-muchos-eloquent

https://unprogramador.com/relacion-1-a-n-en-laravel/

https://diarioprogramador.com/laravel-relaciones-uno-a-muchos-one-to-many/

https://bluuweb.github.io/tutorial-laravel/db-relacional/#relacion-uno-a-muchos-inverso

https://angelguerrero.github.io/angel/exercises/relaciones-en-laravel

==============================================

https://styde.net/laravel-6-doc-eloquent-relaciones/

https://diegooo.com/filtros-dinamicos-con-laravel-eloquent/

https://www.laraveltip.com/obtener-relaciones-de-modelos-automaticamente-en-laravel/

https://ajgallego.gitbook.io/laravel-5/capitulo_3/base_de_datos_eloquent_orm

https://documentacionlaravel.com/docs/9.x/eloquent-relationships



Comentarios

Entradas populares de este blog

Filtrando por fecha

10 videojuegos gratis para aprender JavaScript en línea

reloj obs---datetime.lua