Laravel 5.6 – Как получить последние X имен гостей для сделки с номером?

Я не могу понять, как структурировать эффективный запрос Eloquent для следующего сценария.

Пользователи могут оставаться во многих местах, таких как комнаты, квартиры, дома, поэтому у нас есть полиморфная stayable_locations таблица, но мы фокусируемся только на комнате stayable_type этой таблицы. Когда персонал нажимает на номер, мы хотим отобразить все доступные предложения номеров (если таковые доступны в таблице room_deals), а также последних 3 гостей для каждого предложения номеров (если есть).

Попытка получить этот вывод из следующих таблиц с помощью красноречия:

Room 111 (desired output for room deals and guests below)
- Room Deal #1 -> Able, Kane, Eve
- Room Deal #2 -> Eve, Adam

------------------------------------------
$room = Room::where('id',111)->first(); // room 111
// Eloquent query, not sure how to setup model relations correctly
// To get last 3 guest names per room deal [if any] in an efficient query
$room->roomDeals()->withSpecificRoomDealLast3RoomGuestNamesIfAny()->get();

Вот структура таблицы:

stayable_locations table [polymorphic]:
id | stayable_id | stayable_type | room_deal_id | room_guest_id
----------------------------------------------------------------
1  |     111     |     room      |       0      | 3 (Steve no room deal)
2  |     111     |     room      |       1      | 1 (Adam room deal) 
3  |     111     |     room      |       1      | 2 (Eve room deal)
4  |     111     |     room      |       1      | 4 (Kane room deal)
5  |     111     |     room      |       1      | 5 (Able room deal)
6  |     111     |     room      |       2      | 1 (Adam room deal)
7  |     111     |     room      |       2      | 2 (Eve room deal)

room_deals table:
id | room_id | room_deal
-----------------------
1  |   111   | Deal A
2  |   111   | Deal B


users table:
id | name
------------
1  | Adam
2  | Eve
3  | Steve
4  | Kane
5  | Able

ОБНОВЛЕНИЕ: показаны соответствующие модели

Модель пользователя:

class User extends Authenticatable {
    public function stayableLocations() {
      return $this->morphMany('App\StayableLocation', 'stayable');
    }
}

Модель RoomDeal:

class RoomDeal extends Model {
    public function room() {
        return $this->belongsTo('App\Room');
    }

    public function guests() {
        return $this->belongsToMany('App\User', 'stayable_locations', 'room_deal_id', 'room_guest_id');
    }
}

Модель StayableLocation:

class StayableLocation extends Model {
    public function stayable() {
        return $this->morphTo();
    }

    public function room() {
        return $this->belongsTo('App\Room', 'stayable_id');
    }
}

Модель комнаты:

class Room extends Model {
  public function stayableLocations() {
    return $this->morphMany('App\StayableLocation', 'stayable');
  }

  public function roomDeals() {
      return $this->hasMany('App\RoomDeal');
  }
}

Любая идея, как получить желаемый результат с помощью эффективного красноречивого запроса?

Я удалил свой ответ, оказывается, Eloquent не поддерживает этот тип запроса. Если вы проверите проблемы, решаемые этим запросом на вытягивание, вы можете попробовать и другие решения: github.com/laravel/docs/pull/4918. Удачи!

newUserName02 09.03.2019 22:46

@jonasstaudenmeir Я заметил здесь ваш пакет (github.com/staudenmeir/красноречиво-нетерпеливый-лимит), но после его установки я не уверен, как правильно применить отношения модели, чтобы получить желаемый результат в виде красноречивых нетерпеливых ограниченных результатов (поскольку здесь используется полиморфное отношение, это делает его немного сложнее). Есть идеи?

Wonka 11.03.2019 01:57

Вы пробовали удаленный ответ newUserName02 (у вас он все еще где-то есть?) в сочетании с пакетом? Как определяется «последний»?

Jonas Staudenmeir 11.03.2019 17:26

Спасибо вам, ребята! Разобрался с решением ниже. Спасибо за руководство newUserName02 и пакет @JonasStaudenmeir!

Wonka 11.03.2019 19:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
4
233
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял это из вспомогательных комментариев в моем вопросе. Вот так:

  1. Laravel не имеет этого стандартного (посмотреть здесь), поэтому нам придется использовать сторонний пакет.
  2. Установите пакет стауденмейр/красноречиво-нетерпеливый-лимит по ссылкам и следуйте примеру использования.
  3. Это то, что нужно было изменить выше [по-прежнему используется то же определенное отношение выше для ниже ...], просто добавлено use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;:
class User extends Authenticatable {
  use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
  ... 
}

class RoomDeal extends Model {
  use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
  ...
}
  1. Рабочий запрос с вложенным лимитом через красноречие, спасибо комментаторам и справке по пакету:
$room = Room::find(111);

$deals3Guests = $room->roomDeals()                                    // query deals
                ->with(['guests' => function($query) {                // eager load guests
                    $query->orderBy('stayable_locations.id', 'desc')  // get latest guests
                          ->limit(3);                                // limit to 3
                }])
                ->get();

Другие вопросы по теме