HasOne-one to one-belongsTo
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.
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();
});
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);
}
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
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:
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())
];
}
}
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.
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.
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.
========================================================================
Para una relación uno a uno, use el método hasOne and belongsTo en el modelo para acceder a cada uno de los otros modelos.
También crearemos migración con clave externa, recuperaremos registros usando el modelo, insertaremos nuevos registros, actualizaremos registros, etc.
Crearemos la tabla Usuario y Teléfono. El modelo de User puede estar asociado con un modelo de teléfono. Para definir esta relación, colocaremos un método de phone en el modelo User. El método de phone debe llamar al método hasOne y devolver su resultado.
Crear migración
Ahora tenemos que crear la migración para la tabla de usuarios y teléfonos. también agregaremos la clave externa con la tabla de usuarios.
Crear Tabla de Migración de Usuarios
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
Crear Tabla de Migración de Teléfonos con Clave Foránea
Schema::create('phones', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('phone_no');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Integridad referencial
Una de las principales bondades de las claves foráneas es que permiten eliminar y actualizar registros en cascada, todos los registros relacionados son eliminados de acuerdo a las relaciones de clave foránea. Una alternativa es no eliminar los registros relacionados, y poner el valor de la clave foránea a NULL.
Las opciones estándar cuando se elimina una registro con clave foránea son:
ON DELETE RESTRICT es la acción predeterminada, y no permite una eliminación si existe un registro asociado, como se mostró en el ejemplo anterior.
ON DELETE NO ACTION hace lo mismo.
ON DELETE SET DEFAULT actualmente no funciona en MySQL - se supone que pone el valor de la clave foránea al valor por omisión (DEFAULT) que se definió al momento de crear la tabla.
ON DELETE CASCADE, y una fila en la tabla padre es eliminada, entonces se eliminarán las filas de la tabla hijo cuya clave foránea sea igual al valor de la clave referenciada en la tabla padre. Esta acción siempre ha estado disponible en MySQL.
ON DELETE SET NULL, las filas en la tabla hijo son actualizadas automáticamente poniendo en las columnas de la clave foránea el valor NULL. Si se especifica una acción SET NULL, debemos asegurarnos de no declarar las columnas en la tabla como NOT NULL.
Crear modelo y agregar relación en ambos modelos
En el modelo de usuario, podemos crear la función phone () y agregar la relación del modelo de teléfono usando el método hasOne.
Modelo de usuario:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/*** Get the phone associated with the user.*/
public function phone()
{
return $this->hasOne(Phone::class);
}
}
Modelo de teléfono :
podemos acceder al modelo de Phone desde nuestro modelo de User. A continuación, definamos una relación en el modelo Phone que nos permitirá acceder al usuario propietario del teléfono. Podemos definir el inverso de una relación hasOne usando el método belongsTo.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model
{
/*** Get the user that owns the phone.*/
public function user()
{
return $this->belongsTo(User::class);
} }
Si la clave externa en el modelo de Phone no es user_id, puede pasar un nombre de clave personalizado como segundo argumento para el método de belongsTo.
public function user()
{
return $this->belongsTo(User::class, 'foreign_key');
}
Recuperar registros usando el modelo:
Una vez que se define la relación, podemos recuperar el registro relacionado usando las propiedades dinámicas de Eloquent. Entonces, aquí podemos usar el modelo de usuario con función de teléfono.
$phone = User::find(1)->phone;
$user = Phone::find(1)->user;
Crear registros usando el modelo
$user = User::find(1);
$phone = new Phone;
$phone->phone_no = '9876543210';
$user->phone()->save($phone);
$phone = Phone::find(1);
$user = User::find(1);
$phone->user()->associate($user)->save();
HasOne funciona exactamente igual que HasMany solo con una desviación. Eso es que Laravel siempre asume que solo hay un modelo relacionado.
Una publicación está escrita por un autor, por lo que el autor tiene una publicación. En esta relación, la tabla de publicaciones tiene un campo author_id que contiene la clave externa de la tabla de authors, al igual que HasMany.
En el modelo Autor, la relación se define así:
public function post(): HasOne
{
return $this->hasOne(Post::class);
}
Y al igual que HasMany, conectar la publicación con el autor se puede hacer así:
$author->post()->save($post);
Cuando la relación está configurada correctamente, puede recuperar el modelo Post de esta manera:
$author->post
=================
https://blog.pleets.org/article/relacion-uno-a-uno-eloquent
https://diarioprogramador.com/laravel-relaciones-uno-a-uno-one-to-one/
https://diegooo.com/relacion-uno-a-uno-ejemplo-para-laravel-8/
https://diarioprogramador.com/laravel-relaciones-uno-a-uno-one-to-one/
https://medium.com/@danielmayurilevano/laravel-eloquent-relaciones-uno-a-uno-9c7652364d6d
https://angelguerrero.github.io/angel/exercises/relaciones-en-laravel
============================
https://diegooo.com/filtros-dinamicos-con-laravel-eloquent/
https://styde.net/laravel-6-doc-eloquent-relaciones/
https://iescelia.org/docs/dwes/_site/laravel/eloquent.html
https://andresledo.es/php/laravel/eloquent/#Consultar_registros_con_Eloquent
https://programacionymas.com/blog/consultas-laravel-eficientes-usando-eloquent
https://bluuweb.github.io/tutorial-laravel/db-relacional/#configuraciones-iniciales

Comentarios
Publicar un comentario