Красноречивые пользовательские отношения «принадлежит» для нескольких таблиц - PullRequest
0 голосов
/ 11 марта 2020

У меня следующая структура БД:

  • Таблица Транспортные средства : id, car_id, plane_id
  • Таблица Автомобили : id, модель ...
  • Таблица Самолеты : идентификатор, модель ...

Когда новая запись добавляется в таблицу Транспортные средства , если это Car , будет установлен car_id , а plane_id останется пустым, и наоборот, Я знаю, что это плохая структура , но она унаследована, и я не могу ее изменить.

Поэтому я хочу определить отношение в модели транспортного средства, где оно может извлечь объект Car или объект Plane в соответствии с тем, какой ключ пусто, car_id или plane_id . И между прочим, я уже определил две взаимосвязи, которые будут извлекать объект Car и объект Plane отдельно.

public function carVehicle()
{
    return $this->belongsTo(Car::class, 'car_id');
}

public function planeVehicle()
{
    return $this->belongsTo(Plane::class, 'plane_id');
}

1 Ответ

0 голосов
/ 11 марта 2020

Лучше всего это обработать с помощью отношения Polymorphic (подробнее см. https://laravel.com/docs/5.8/eloquent-relationships#polymorphic -отношение ), но есть способы обойти это, если ваша текущая модель не соответствует структуре, и вы можете ' t изменить его.

У вас может быть третий метод, который добавляет оба к Collection и возвращает first() (поскольку вы говорите, что car_id или plane_id всегда будет null ):

Vehicle.php:

public function getChildVehicleAttribute(){
  return collect([$this->carVehicle, $this->planeVehicle])
  ->filter(function($record) {
    return $record != null;
  })->first();
}

Затем вы получите доступ с помощью следующего запроса:

$vehicle = Vehicle::with(['carVehicle', 'planeVehicle'])->first()->child_vehicle;
// OR
$vehicles = Vehicle::with(['carVehicle', 'planeVehicle'])->get();
foreach($vehicles AS $vehicle){
  $childVehicle = $vehicle->child_vehicle;
  // dd($childVehicle, etc.)
}

Предложение with() будет загружать обе связи поэтому $this->carVehicle и $this->planeVehicle не инициируют дополнительные вызовы базы данных, а вызов child_vehicle для любого экземпляра Vehicle вернет либо Car, либо Plane (или null, если ни одно из них не определено)

...