#php #laravel #eloquent #laravel-7
#php #ларавель #красноречивый #laravel-7
Вопрос:
Я разрабатываю систему бронирования, в которой используется Laravel 7.0
итак, в этой системе я создал таблицу под названием «bookings»
и я создал его модель под названием Booking.php
внутри этого Booking.php Я ввел функцию отношения, чтобы присоединить ее модель к таблице транзакций, как показано ниже
public function transaction()
{
return $this->belongsTo('AppModelsTransaction', 'id', 'booking_id');
}
внезапно появляется новое требование, и у этого бронирования будет свой дочерний элемент
поэтому, чтобы различать родительский элемент бронирования и его дочерний элемент, я добавляю новый столбец в таблицу бронирования под названием
‘parent_booking_id’
Я не хочу слишком сильно изменять функцию кода, поэтому я думаю о создании условия, чтобы убедиться, что отношение точек бронирования к правильной транзакции
Я думаю о написании подобного кода
public function transaction()
{
return $this->belongsTo('AppModelsTransaction', 'parent_booking_id' ?? 'id', 'booking_id');
}
но это работает не так, как предполагалось
логика такова
Если parent_booking_id существует, то присоедините столбец ‘booking_id’ при транзакции таблицы к столбцу ‘parent_booking_id’ при бронировании таблицы
ещё
он присоединит столбец ‘booking_id’ при транзакции таблицы к столбцу ‘id’ при бронировании таблицы
Комментарии:
1. да, очевидно, что оно не работает, поскольку
'parent_booking_id'
является строкой и поэтому всегда будет аргументом. Вы можете попробовать$this->parent_booking_id ? 'x' : 'y'
, но, возможно, даже лучше создать 2 отношения для ясности2. пробовал $this->parent_booking_id, но он всегда возвращает null, поэтому не может использоваться как условный, как мне создать 2 отношения без изменения текущего кода, который уже использует функцию транзакции
Ответ №1:
Я не совсем уверен, все ли я понял.
Я не использую такую логику внутри моделей, но если вы действительно этого хотите. Я не уверен, но я думаю, что это может сработать.
public function parent_booking()
{
$this->belongsTo('AppModelsBooking', 'parent_booking_id');
}
public function transaction()
{
if ($this->has('parent_booking')) {
return $this->hasOne('AppModelsTransaction', 'parent_booking_id', 'booking_id');
} else {
return $this->hasOne('AppModelsTransaction', 'booking_id');
}
}
Если вы пытаетесь достичь этого:
Когда у бронирования есть parent_booking, прикрепите транзакцию к parent_booking, иначе прикрепите ее к бронированию.
Для этого я предлагаю сделать что-то более похожее на это.
public function parent_booking()
{
$this->belongsTo('AppModelsBooking', 'parent_booking_id');
}
public function childs_booking()
{
$this->hasMany('AppModelsBooking', 'parent_booking_id');
}
Затем вы можете сделать это в контроллере:
$booking = Booking::with('parent_booking')->find($id);
if ($booking->has('parent_booking')) {
//do some stuff.
$booking->parent_booking->transaction->associate($transaction->id);
} else {
//do other stuff
$booking->transaction->associate($transaction->id);
}
И, конечно же, вы захотите получить правильную транзакцию. Существует пример извлечения каждого бронирования.
$bookings = Booking::with(array('parent_booking', function($query) {
return $query->with('transaction');
}))->with('transaction')->get();
foreach($bookings as $booking) {
if ($booking->has('parent_booking')) {
$transaction_to_use = $booking->parent_booking->transaction;
} else {
$transaction_to_use = $booking->transaction;
}
}
Вы также можете выполнить что-то вроде этого:
$transactions = Transaction::with(array('booking', function($query) {
return $query->with('childs_booking');
}))->get();
Таким образом, вы получаете все транзакции с их бронированием. У вас также есть каждое дочернее бронирование.
Ответ №2:
Наконец-то найдено решение этой проблемы
правильный способ исправить это:
создание 2 отношений
а затем изменяет код, используя условие where, чтобы убедиться, что он передает правильное отношение на основе значения резервирования
НО поскольку этот способ исправления требует значительных изменений кода, я пытаюсь найти другие способы
и другие способы — вместо создания ‘parent_booking_id’ я создаю столбец с именем ‘primary_booking_id’
этот ‘primary_booking_id’ всегда будет содержать booking_id первого выполняемого бронирования
итак, при первом создании модели я обновлю ее, чтобы она получила booking_id
$booking->update(['primary_booking_id' => $booking->id]);
а затем во время создания его дочернего элемента я введу primary_booking_id в создание
$input['primary_booking_id'] => $previous_booking->primary_booking_id;
$booking::create($input);
таким образом, способ обработки этого требует внесения незначительных изменений в функцию связи транзакций бронирования, как показано ниже
public function transaction()
{
return $this->hasOne('AppModelsTransaction', 'booking_id', 'primary_booking_id');
}
вуаля!
это работает, и никаких серьезных изменений не требуется