Laravel добавляет условие внутри отношения публичной функции модели

#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');
}
 

вуаля!

это работает, и никаких серьезных изменений не требуется