38. Relación uno a uno

En una relación uno a uno en una base de datos, una fila de una tabla se relaciona con exactamente una fila en otra tabla y viceversa. Esta relación se establece mediante la creación de una clave foránea en la tabla que representa el lado "muchos" de la relación, que apunta a la clave primaria de la tabla que representa el lado "uno".

Un ejemplo común de una relación uno a uno es una tabla de usuarios y una tabla de perfiles de usuario, donde cada usuario tiene exactamente un perfil y cada perfil pertenece a un solo usuario. En este caso, la clave primaria de la tabla de usuarios se convierte en la clave foránea en la tabla de perfiles de usuario, estableciendo así la relación uno a uno.


6 comentarios

Inicia sesión para comentar

Comentarios:

  • Angel Alberto Atencio Caldera

    Angel Alberto Atencio Caldera hace 1 año

    Si no les realiza la relación en la BBDD  deben cambiar el motor de BBDD en el archivo  /config/database.php 

    esto:

    'engine' => null,

    por esto:

    'engine' => 'InnoDB',

  • Mauricio Giraldo

    Mauricio Giraldo hace 2 años

    php artisan make:model Prueba -mf 

    Con este comando nos crea el modelo, la migración y el factori de una sola 

  • Jhon Lozano Lozano Arce

    Jhon Lozano Lozano Arce hace 2 años

    Buenas noche.

    cual seria la lógica de tener una relación uno a uno entre las tablas user y perfiles?

    si la tabla user tiene una relación uno a uno con la tabla perfiles y la tabla perfiles tiene 4 campos, no seria mejor colocar los campos de la tabla perfiles en la tabla user?

    • Walter hace 2 años

      ? Hola Jhon, la lógica es similar a la aplicada con el campo dirección que es multivalor y por ese motivo creamos una tabla direcciones con esos valores. 

       

      Todo depende de la lógica de negocio, en este caso es una relación uno a uno pero si llegase a cambiar y debemos permitir múltiples perfiles para cada usuario, nuestra estructura no sería escalable.

       

    • Jhon Lozano Lozano Arce hace 2 años

      si asi es, funcionario si un usuario tuviera mas de un perfil

  • Walter

    Walter hace 2 años

    ? Relaciones uno a uno

             En este tipo de relaciones existe una entidad fuerte y una entidad débil.

             Por ejemplo tenemos las tablas users y profiles.

             Entidad fuerte: no depende de otra entidad.

             Entidad débil: su existencia esta condicionada por la existencia de otra entidad.

             Creamos primero la entidad fuerte.

             Como ya tenemos creada la tabla users pasamos a crear profiles:

     

        php artisan make:migration create_profiles_tables

     

             Luego creamos el modelo que se va a encargar de administrar esta tabla:

     

        php artisan make:model Profile

     

             Vamos al archivo de migración y especificamos los campos en el método up:

     

        $table->id();
    
        $table->string('title', 45);
        $table->text('biografia');
        $table->string('website', 45);
    
        $table->unsignedBigInteger('user_id')->unique();
        $table->foreign('user_id')
        	->references('id')
        	->on('users')
        	->onDelete('cascade')  //otra opción es: set null 
        	->onUpdate('cascade');
    
        $table->timestamps();

     

             La forma que tenemos de relacionar ambas tablas es agregando un nuevo campo llamado user_id donde almacenaremos el id de un determinado usuario. El campo user_id debe ser del mismo tipo que el campo id que hacemos referencia (entero grande sin signo), de otra forma no podremos agregar la restricción de llave foránea.

             Ahora ejecutamos la migración:

     

        php artisan migrate

     

             Eloquent trata a cada registro como si fuera un objeto. Objeto que es instanciado de su modelo, por eso vamos al modelo User y le agregamos un nuevo método encargado de recuperar la información del perfil que le corresponde al usuario:

     

        public function profile() {
        	$profile = Profile::where('user_id', $this->id)->first();
        	return $profile;
        }

     

             Podemos hacer lo mismo de una forma equivalente pero escribiendo menos:

     

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

     

             De esta forma debemos importar la clase al principio:

     

        use App\Models\Profile;

     

             No necesitamos importar la clase si escribimos la clase como cadena de la siguiente forma:

     

        public function profile() {
        	return $this->hasOne('App\Models\Profile');
        }

     

             El método hasOne está considerando que la llave foránea de la tabla profiles es users_id y la llave primaria de la tabla users es id, si les dimos otros nombres por ejemplo foreign_key y local_key respectivamente, debemos indicarlos como parámetros:

     

        public function profile() {
        	return $this->hasOne('App\Models\Profile','foreign_key','local_key');
        }

     

             Vemos entonces que si seguimos las convenciones escribiremos menos código.

             Ahora consideremos el caso contrario donde recuperamos el perfil y queremos obtener los datos del usuario, en este caso agregamos un nuevo método al modelo Profile:

     

        public function user() {
        	$user= User::find($this->user_id);
        	return $user;
        }

     

             También tenemos una forma equivalente:

     

        public function user() {
        	return $this->belongsTo('App\Models\User');
        }

     

             Si pusimos otro nombre que no sea user_id como llave foránea debemos especificarlo como segundo parámetro y si la llave primaria de Users no fuera id lo indicamos como tercer parámetro.

     

  • Walter

    Walter hace 2 años

    ? Nota

          Nombramos las tablas intermedias con los nombres de las tablas en singular, separados por un guion bajo y en orden alfabético. 

          Con los nombres en español se considera el singular simplemente sacándole la ese. Ej. roles → role (en lugar de rol).

     

  • Walter

    Walter hace 2 años

    Buenas! ¿dónde podemos consultar las equivalencias de tipos con MySQL cuando completamos los campos en las migraciones?