-1

I have two tables in my project and there are two relationships between these two tables. One of these two relationships is one-to-one and the other one is a one-to-many relationship.

My tables:

+--------------+-----------------+------+-----+---------+----------------+
| Field        | Type            | Null | Key | Default | Extra          |
+--------------+-----------------+------+-----+---------+----------------+
| id           | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| username     | varchar(255)    | NO   | UNI | NULL    |                |
| password     | varchar(255)    | NO   |     | NULL    |                |
| email        | varchar(255)    | NO   | UNI | NULL    |                |
| common_name  | varchar(255)    | NO   |     | NULL    |                |
| phone_number | varchar(13)     | YES  | UNI | NULL    |                |
| role         | varchar(255)    | NO   |     | NULL    |                |
| created_at   | timestamp       | YES  |     | NULL    |                |
| updated_at   | timestamp       | YES  |     | NULL    |                |
+--------------+-----------------+------+-----+---------+----------------+

+---------------------+-----------------+------+-----+---------+----------------+
| Field               | Type            | Null | Key | Default | Extra          |
+---------------------+-----------------+------+-----+---------+----------------+
| id                  | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| unit_number         | int             | NO   | UNI | NULL    |                |
| owner_id            | bigint unsigned | NO   |     | NULL    |                |
| resident_id         | bigint unsigned | YES  |     | NULL    |                |
| availability_status | varchar(255)    | NO   |     | NULL    |                |
| number_of_rooms     | int             | NO   |     | NULL    |                |
| meterage            | int unsigned    | NO   |     | NULL    |                |
| description         | text            | YES  |     | NULL    |                |
| monthly_rent        | int             | YES  |     | NULL    |                |
| created_at          | timestamp       | YES  |     | NULL    |                |
| updated_at          | timestamp       | YES  |     | NULL    |                |
+---------------------+-----------------+------+-----+---------+----------------+

Relations in my models:

User model:

public function unitOwner()
{
    return $this->hasMany(Unit::class, 'owner_id', 'id');
}

public function unitResident()
{
    return $this->hasOne(Unit::class, 'resident_id', 'id');
}

Unit model:

public function ownerUser()
{
    return $this->belongsTo(User::class, 'owner_id');
}

public function residentUser()
{
    return $this->belongsTo(User::class,'resident_id');
}

I want, for example, when I delete a user, that the deleted user's ID will be deleted from the unit associated with that user (whether he is a resident of the unit or the owner of the unit). And the availability_status column of that unit, for example, can change from occupied to unoccupied.

I have a few ways in mind to implement this mode, but in all of these modes my code becomes very long. What is the shortest way to implement this?

philipxy
  • 14,867
  • 6
  • 39
  • 83
  • One way is to make new migration and change field of units.owner_id adding `->onDelete('cascade')` ([docs](https://laravel.com/docs/10.x/migrations#foreign-key-constraints)). That is the better solution. Other way is to set `deleted` event in observer of User model. – Tpojka Aug 14 '23 at 09:19
  • Thank you, but I don't want to delete the related unit. I want to change the availability_status of unit and delete the user.id from resident_id column – mahdi_sheykh Aug 14 '23 at 09:36
  • Ok, don't set cascade on DB level in migration. Instead, that can be achieved in deleted or deleting event of `User`'s observer. – Tpojka Aug 14 '23 at 10:15
  • "I have a few ways in mind to implement this mode, but in all of these modes my code becomes very long I am looking for the shortest way to implement this" You should post that long code to [this site](https://codereview.stackexchange.com/) asking for different way of implementation. – Tpojka Aug 14 '23 at 10:17
  • 1
    Before you post at [codereview.se], be sure to read [A guide to Code Review for Stack Overflow users](//codereview.meta.stackexchange.com/a/5778), as some things are done differently over there - e.g. question titles should simply say what the code *is for*, as the question is always, "How can I improve this?". Be sure that the code works correctly; include your unit tests if possible. You'll likely get some suggestions on making it more efficient, easier to read, and better tested. – Toby Speight Aug 14 '23 at 10:24

1 Answers1

0

The first thing you need to do is define a migration to set the `owner_id' to null when you delete a user:

$table->foreignId('owner_id')
    ->nullable()
    ->constrained()    
    ->cascadeOnUpdate()
    ->nullOnDelete();

Then, to handle the availability_status, you can use the model observer like this:

class UserObserver
{
    public function deleted(User $user): void
    {
        $user->unitOwner()->update(['owner_id' => null, 'availability_status' => 'unoccupied']);

        $user->unitResident()->update(['resident_id' => null, 'availability_status' => 'unoccupied']);
    }
}
Nothehi
  • 695
  • 6
  • 19