Иногда модель может иметь множество связанных моделей, но вы хотите легко получить "самую последнюю" или "самую старую" связанную модель. Например, модель User
может быть связана со многими моделями Order
, но вы хотите определить удобный способ взаимодействия с последним заказом пользователя. Для этого можно использовать тип отношения hasOne
в сочетании с методами ofMany
:
/**
* Получить последний (самый новый) заказ пользователя
*/
public function latestOrder()
{
return $this->hasOne(Order::class)->latestOfMany();
}
Аналогично, вы можете определить метод для получения "самой старой" (первой) связанной модели отношения:
/**
* Получить самый старый заказ пользователя
*/
public function oldestOrder()
{
return $this->hasOne(Order::class)->oldestOfMany();
}
По умолчанию методы latestOfMany
и oldestOfMany
извлекают самую последнюю или самую старую связанную модель на основе первичного ключа модели. Этот ключ должен быть сортируемым. Чтобы использовать данные другого столбца, используйте метод ofMany
. Он принимает в качестве первого аргумента сортируемый столбец и то, какую агрегатную функцию (min
или max
) применить при запросе связанной модели.
Например, так можно получить самый дорогой заказ пользователя:
/**
* Получить самый дорогой заказ пользователя
*/
public function largestOrder()
{
return $this->hasOne(Order::class)->ofMany('price', 'max');
}
Поскольку PostgreSQL не поддерживает выполнение функции
MAX
для столбцов UUID, в настоящее время невозможно использовать отношения "один-из-многих" в сочетании со столбцами UUID PostgreSQL.
Продвинутые возможности отношения Один-из-многих
Критерии сортировки при выборе могут быть сложными. Например, модель Product
может иметь множество связанных с ней моделей Price
, которые сохраняются в системе даже после публикации новых цен - например, чтобы можно было посмотреть динамику изменения цены продукта. Кроме того, новые данные о ценах на продукт могут быть опубликованы заранее, чтобы вступить в силу в определённую дату - через колонку published_at
.
Таким образом, нам нужно получить последние опубликованные цены, если дата публикации не находится в будущем. Кроме того, если две цены имеют одинаковую дату публикации, мы предпочтем цену с наибольшим ID. Для этого в метод ofMany
нужно передать массив, который содержит сортируемые столбцы, определяющие последнюю цену. Кроме того, в качестве второго аргумента метода ofMany
передаётся функция, которая будет отвечать за добавление дополнительного фильтра по дате публикации:
/**
* Получить актуальную цену на продукт
*/
public function currentPricing()
{
return $this->hasOne(Price::class)->ofMany([
'published_at' => 'max',
'id' => 'max',
], function ($query) {
$query->where('published_at', '<', now());
});
}