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

En este tutorial aprenderás cómo crear relaciones «uno a uno» (One to One) en Laravel. Este tipo de relaciones son una manera de establecer una conexión entre dos modelos de datos (un modelo representa una tabla de la base de datos), donde un registro en un modelo está relacionado con un único registro en otro modelo. También aprenderás cómo poblar las tablas con datos de prueba usando la librería Faker 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.  Tener un proyecto Laravel conectado a una base de datos.
  3.  Editor de textos como VS Code o PHPStorm.

Planteamiento

Se cuenta con un sistema de usuarios los cuales cada uno tiene un perfil único, por lo que el sistema tiene dos modelos User y Profile en donde un perfil pertenece a un usuario y un usuario solo tiene un perfil, en este ejemplo debe de usarse una relación de uno a uno. Para implementar las relaciones «uno a uno» (One to One) en Laravel a continuación los pasos:

1. Crear modelos y migraciones

Para este ejemplo sólo crearás el modelo Profile con su migración ya que Laravel por defecto ya tiene creado el modelo User y la migración users. Para crear el modelo Profile abre la terminal de comandos en la raíz de tu proyecto en Laravel y ejecuta la instrucción:

php artisan make:model Profile -m

2. Configurar archivo de migraciones

Con tu editor de textos abre el archivo database/migrations/…create_profiles_table.php agrega los siguientes campos:

Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->string('phone');
    $table->string('address');
    $table->string('facebook');
    $table->string('website');

    //foreign key
    $table->unsignedBigInteger('user_id')->unique();
    $table->foreign('user_id')->references('id')
        ->on('users')
        ->onDelete('cascade')
        ->onUpdate('cascade');

    $table->timestamps();
});

En el código anterior el método unsignedBigInteger() asigna al campo user_id un tipo de dato entero, positivo y soporta un valor muy grande, con unique() solo permite un id único de la tabla users por registro. El método foreign() define la llave foránea y la relación entre el campo user_id de la tabla profiles y el campo id de la tabla users.

3. Relacionar los modelos User y Profile

Para crear las relaciones entre User y Profile a nivel de modelo abre el archivo app/Models/User.php y como un user solo tiene un profile se usa el método en singular y se usa hasOne(). Agrega el siguiente método al archivo:

//relationships One to One
public function profile(){
    return $this->hasOne(Profile::class);
}

Para hacer la relación inversa abre el archivo app/Models/Profile y como un profile pertenece a un solo user el método debe estar en singular y se utiliza belongsTo(). Agrega la siguiente función al archivo:

public function user(){
    return $this->belongsTo(User::class);
}

4. Agregar datos de prueba

Ahora puedes poblar las tablas de la base de datos con información falsa de prueba, para este ejemplo usaré Factories, Laravel por defecto ya tiene un factory para el modelo User así que solamente crearé el factory del modelo Profile para ello ejecuta la siguiente instrucción en la terminal de comandos:

php artisan make:factory ProfileFactory

4.1 Configurar ProfileFactory

Para configurar el recién creado factory abre el archivo database/factories/ProfileFactory.php para agregar información falsa de prueba vas a utilizar la librería de Laravel Faker, pega el siguiente código en tu archivo:

<?php

namespace Database\Factories;

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

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Profile>
 */
class ProfileFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        $users = User::all();

        return [
            'phone' => $this->faker->phoneNumber(),
            'address' => $this->faker->address(),
            'facebook' => $this->faker->email(),
            'website' => $this->faker->sentence(1) . 'com',
            'user_id' => $this->faker->unique()->numberBetween(1, $users->count())
        ];
    }
}

4.2 Configurar archivo DatabaseSeeder

Para que corran los factories abre el archivo database/seeders/DatabaseSeeder.php y al inicio del archivo importa los modelos User y Profile:

use App\Models\User;
use App\Models\Profile;

Y dentro del método run agrega estas líneas de código:

User::factory(10)->create();
Profile::factory(10)->create();

Corre las migraciones y los factories ejecutando el comando:

php artisan migrate:fresh --seed

Abre tu cliente de gestión de base de datos como PHPMyAdmin, Heidi o MySQLWorbench y revisa las tablas profiles y users de tu base de datos, verás que ya están pobladas con los datos de prueba y están manteniendo la relación de uno a uno entre ellas.

5. Probar la relación uno a uno (One to One) en Laravel

Laravel tiene integrada una muy útil herramienta de desarrollo de línea de comando llamada Tinker la cual permite realizar consultas de prueba a las tablas relacionadas en la base de datos, para usar Tinker desde la terminal ejecuta el comando:

php artisan tinker

Con Tinker puedes verificar si las relaciones entre los modelos User y Profile se hicieron correctamente, para realizar una consulta usa las mismas instrucciones de Eloquent que normalmente utilizas en los controladores. Por ejemplo para consultar los datos del usuario con id 3 ejecuta:

$user = User::find(3);

Te desplegará toda la información de dicho usuario. Si quieres consultar el profile de este usuario y comprobar que las relaciones se hicieron correctamente ejecuta:

$user->profile

Verás que te muestra todos los datos almacenados en el profile de dicho usuario y que el campo user_id de la tabla profiles es el mismo valor de la tabla users ya que están relacionados.

Para consultar la relación inversa por ejemplo del profile 8 ejecuta en la terminal:

$profile = Profile::find(8);

Te mostrará los datos del profile con id 8. Para consultar la relación con la tabla users solamente ejecuta:

$profile->user

Como puedes ver se han mostrado los datos de la tabla relacionada. 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 uno (One to One) 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 documentación.
Repositorio del tutorial.

Deja un comentario

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