Удалить запись из отношения «один ко многим»

#php #laravel #phpmyadmin #relationship #one-to-many

#php #laravel #phpmyadmin #отношение #один ко многим

Вопрос:

У меня есть 3 таблицы:

Пользователи

 id
role
email
typable_id
typable_type
  

покупатели

 id
name
address
avatar
email
residential_id
  

остаточные значения

 id
name
city 
state
  

И вот моя модель, которая показывает взаимосвязь

User.php

 public function typable()
{
  return $this->morphTo();
}
  

Buyer.php

 public function residential()
{
  return $this->belongsTo(Residential::class);
}

public function user()
{
  return $this->morphMany(User::class, 'typable');
}
  

Residential.php

 public function buyer()
{
  return $this->hasMany(Buyer::class);
}
  

Если я хочу удалить жилое помещение, необходимо удалить всех покупателей из этого жилого помещения. То же, что и пользователи, которые также должны быть удалены при удалении покупателей. Как я могу это сделать? Это то, что находится внутри моего постоянного контроллера для функции уничтожения.

ResidentialController

 public function destroy(Request $request) 
    {
        $residentials = Residential::find($request->input('id'));
        $residentials->id = $request->input('id');
        $residentials->name = $request->input('name');
        $residentials->delete($residentials);

        return response()->json($residentials);
    }
  

Я попытался поместить этот код для удаления покупателей (для пользователей, которых еще нет) внутри destroy(), но ничего не изменилось для удаления покупателей.
$buyers = Buyer::where('residential_id','=',$request->residential_id)->first(); $buyers->delete($buyers);

Хотя это код, который мне удалось выполнить, если я хочу удалить покупателей, пользователи тоже удаляются.

BuyerController

 public function destroy(Request $request)
{
  $users = User::where('email', '=', $request->email)->first();
  $buyers = Buyer::find($request->input('id'));
  $buyers->id = $request->input('id');
  $buyers->name = $request->input('name');
  $buyers->delete($buyers);
  $users->delete($users);

  return response()->json($buyers);
}
  

Я надеюсь, что есть кто-то, кто поможет и научит меня правильному способу.

Ответ №1:

Подход-1

вы можете переопределить функцию удаления для любой модели.

 //Residential.php
public function delete()
{
    $this->buyer->delete(); 
    return parent::delete();
}

//Buyer.php
public function delete()
{
    $this->user->delete(); 
    return parent::delete();
}
  

Теперь, когда вы удаляете любую запись о проживании, цепочка сначала удалит любого связанного пользователя, а затем удалит покупателя и, наконец, удалит запись о проживании.

Подход-2

Вы можете использовать each() метод, чтобы получить всех связанных покупателей, а затем получить всех связанных пользователей.

 $residentials->buyer
->each(function ($b) {
    $b->user->each(function ($u) {
        $u->delete();
    });
    $b->delete();
});
$residentials->delete();
  

Комментарии:

1. Я использую второй подход, и он работает! Большое вам спасибо!!

Ответ №2:

Возможно, вы захотите зарегистрировать события модели, чтобы справиться с этим:

 class Residential extends Model
{
    // Lets use plural form for a HasMany relationship.
    public function buyers()
    {
        return $this->hasMany(Buyer::class);
    }

    protected static function booted()
    {
        static::deleting(function ($user) {
            // I am using Higher Order Message, check this out: https://laravel.com/docs/8.x/collections#higher-order-messages
            $this->buyers->each->delete();
        });
    }
}


class Buyer extends Model
{
    // Lets use the plural form for a MorpMany relationship.
    public function users()
    {
        return $this->morphMany(User::class, 'typable');
    }

    protected static function booted()
    {
        static::deleting(function ($user) {
            $this->users->each->delete();
        });
    }
}

  

И вам нужно удалить только один объект в вашем контроллере:

 class ResidentialController
{
    public function destroy(Request $request)
    {
        $residential = Residential::findOrFail($request->input('id'));
    
        $residential->delete();

        // The framework is gonna automatically convert this to a JSON object. 
        return $residential;
    }
}

class BuyerController
{
    public function destroy(Request $request)
    {
        $buyer = Buyer::findOrFail($request->input('id'));
    
        $buyer->delete();

        // The framework is gonna automatically convert this to a JSON object. 
        return $buyer;
    }
}
  

Комментарии:

1. Вы могли бы сделать $this->users()->delete() , чтобы упростить запрос

2. Хорошая мысль @KennyHorna. Это определенно работает в этом контексте. Но если пользовательская модель содержит дополнительные события, они не будут запущены. Итак, мой код немного лучше.

3. Тогда больше не нужно вводить какие-либо запросы в резидентный контроллер destroy() ?

4. О, запрос на удаление жилого помещения должен быть там, иначе как я могу его удалить, верно?

5. @IrdinaZulkeflee Я обновил свой ответ. Надеюсь, это отвечает на ваш вопрос.