Как я могу отсортировать красноречивый запрос по отношениям один-ко-многим - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть таблица продуктов, и у каждого продукта может быть много инвентаря.Результатом запроса, которого я хочу добиться, является сортировка продуктов по полю цены в таблице инвентаризации.

$products = Product::with(['inventories' => function($query){
    $query->where('count', '>', 0)->orderBy('id');
}])->paginate(16);
return $products;

Результат:

data: [
{
    id: 1,
    brand_id: 3,
    category_id: 5,
    title: "فشارسنج عقربه ای و گوشی پزشکی هانسون مدل وکتو",
    body: null,
    sales: "2",
    image: "images/product/product-image-index-5ca0b4607158f.jpg",
    post_on: "15",
    fast_shipping_cost: "50000",
    weight: "300",
    created_at: "2019-04-21 15:27:58",
    updated_at: "2019-04-21 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 1,
          product_id: 1,
          count: "10",          
          price: "75000",
          expiration_date: null
      }
    ]
},
{
    id: 2,
    brand_id: 3,
    category_id: 5,
    title: "فشارسنج دیجیتال مدیسانا مدل BU 550 Connect",
    body: null,
    sales: "10",
    image: "images/product/product-image-index-5cb70c11cfaf0.jpg",
    post_on: "20",
    fast_shipping_cost: null,
    weight: "250",
    created_at: "2019-04-22 15:27:58",
    updated_at: "2019-04-22 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 2,
          product_id: 2,
          count: "5",          
          price: "150000",
          expiration_date: null
      },
      {
          id: 4,
          product_id: 2,
          count: "7",          
          price: "155000",
          expiration_date: null
      }
    ]
},
{
    id: 3,
    brand_id: 1,
    category_id: 6,
    title: "سوزن تست قند خون تی دی-تین بسته 100 عددی",
    body: null,
    sales: "5",
    image: "images/product/product-image-index-5cbafe568518c.jpg",
    post_on: null,
    fast_shipping_cost: null,
    weight: "150",
    created_at: "2019-04-23 15:27:58",
    updated_at: "2019-04-23 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 3,
          product_id: 3,
          count: "4",          
          price: "98000",
          expiration_date: null
      }
    ]
}
],

Сортировка по $query->where('count', '>', 0)->sortBy('price') Выполнить сортировку только вЗапасы, которые я хочу, чтобы этот вид применялся к продуктам.
Я хочу, чтобы результат был таким:
Сортировка по цене инвентаря, и в результате получается только один запас.
Сначала 150000, затем 98000, а затем 50000

data: [
{
    id: 2,
    brand_id: 3,
    category_id: 5,
    title: "فشارسنج دیجیتال مدیسانا مدل BU 550 Connect",
    body: null,
    sales: "10",
    image: "images/product/product-image-index-5cb70c11cfaf0.jpg",
    post_on: "20",
    fast_shipping_cost: null,
    weight: "250",
    created_at: "2019-04-22 15:27:58",
    updated_at: "2019-04-22 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 2,
          product_id: 2,
          count: "5",          
          price: "150000",
          expiration_date: null
      },    
    ]
},
{
    id: 3,
    brand_id: 1,
    category_id: 6,
    title: "سوزن تست قند خون تی دی-تین بسته 100 عددی",
    body: null,
    sales: "5",
    image: "images/product/product-image-index-5cbafe568518c.jpg",
    post_on: null,
    fast_shipping_cost: null,
    weight: "150",
    created_at: "2019-04-23 15:27:58",
    updated_at: "2019-04-23 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 3,
          product_id: 3,
          count: "4",          
          price: "98000",
          expiration_date: null
      }
    ]
}
{
    id: 1,
    brand_id: 3,
    category_id: 5,
    title: "فشارسنج عقربه ای و گوشی پزشکی هانسون مدل وکتو",
    body: null,
    sales: "2",
    image: "images/product/product-image-index-5ca0b4607158f.jpg",
    post_on: "15",
    fast_shipping_cost: "50000",
    weight: "300",
    created_at: "2019-04-21 15:27:58",
    updated_at: "2019-04-21 15:27:58",
    deleted_at: null,
    inventories: [
      {
          id: 1,
          product_id: 1,
          count: "10",          
          price: "75000",
          expiration_date: null
      }
    ]
},
],

Ответы [ 3 ]

1 голос
/ 29 апреля 2019

Я только что попробовал это на своих столах, и для достижения этого я использовал join вместо with на модели, поэтому, пожалуйста, попробуйте этот подход:

$products = Product::join('inventories as i', 'products.id', '=', 'i.product_id')
            ->where('i.count', '>', 0)
            ->orderBy('i.price') // default is asc order, but as a second parameter you can use desc if you need to.
            ->paginate(16);

- РЕДАКТИРОВАТЬ

$products = Product::with('inventories')->join('inventories as i', 'products.id', '=', 'i.product_id')
            ->where('i.count', '>', 0)
            ->orderBy('i.price') // default is asc order, but as a second parameter you can use desc if you need to.
            ->groupBy('products.id')
            ->paginate(16);
0 голосов
/ 03 мая 2019

Я решил эту проблему:
Сначала добавьте отношение hasOne к модели продукта:

public function latestInventory()
{
    return $this->hasOne(Inventory::class);
}

Затем в ProductController:

$products = Product::with(['latestInventory' => function($query) {
    $query->where('count', '>', 0)->orderBy('id');
}]);
$products = $products->get();
$products = $products->sortBy('latestInventory.price')->paginate(16);

return $products->values()->toArray();

Для коллекции Paginate:
В ASP (AppServiceProvider.php) при способе загрузки:

Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') {
        $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
        return new LengthAwarePaginator(
            $this->forPage($page, $perPage),
            $total ?: $this->count(),
            $perPage,
            $page,
            [
                'path' => LengthAwarePaginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ]
        );
    });

В приложении / Support / Collection.php:

<?php

namespace App\Support;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection as BaseCollection;
class Collection extends BaseCollection
{
    public function paginate($perPage, $total = null, $page = null, $pageName = 'page')
    {
        $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

        return new LengthAwarePaginator(
            $this->forPage($page, $perPage),
            $total ?: $this->count(),
            $perPage,
            $page,
            [
                'path' => LengthAwarePaginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ]
        );
    }
}
0 голосов
/ 29 апреля 2019

Попробуйте это

$products = Product::with(['inventories' => function($query){
    $query->where('count', '>', 0)->orderBy('id');
}])->join('inventories','product.id','=','inventories.product_id')
->select('product.*)->orderBy('inventories.price')
->paginate(16);
return $products;

В настоящее время в Eloquent нет функции для сортировки по отношению, необходимо выполнить объединение для сортировки по отношению. Также не забудьте добавить select ('product. *) При присоединении, иначе есть некоторые проблемы с аномалиями в laravel, который заменяет основной идентификатор на идентификатор присоединяющейся таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...