Возврат определенных столбцов с суммой и счетом из коллекции отношений - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть модели Product, ProductVariant и Department

Отдел:

id | name | ....

Продукт:

id | name | sku | department_id | ....

ProductVariant:

id | product_id | quantity | ....

И все связаны друг с другом, как:

  • Отношения products: Отдел hasMany Продукты
  • Отношения department: Продукт belongsTo Отдел
  • Отношения variants: Продукт hasMany Варианты продукта
  • Отношения product: Продукт belongsTo Продукт

Все работает, как и ожидалось, между отношениями по Eloquent звонкам

Теперь, используя Eloquent, я пытаюсь получить коллекцию из следующих столбцов:

product.id | product.name | product.variant_count | product.stock | department.name

Под product.stock Я имею в виду: $product->variants->sum('quantity'), но мне трудно получить SUM внутри with() метод

Что я пробовал до сих пор:

      $products = Product::select('id', 'name', 'sku', 'department_id') //gives product.name, sku, etc
            ->withCount('variants')                    //gives product.variants_count
            ->with(['variants' => function($query) {
                $query->select('id', 'product_id', 'quantity'); //gives variants->each.quantity
            }])
            ->with(['department' => function($query) {
                $query->select('id', 'name');              //gives department.name
            }]);

Этот код дает что-то вроде этого:

[
{
    "id": "2",
    "name": "Letv LU50609 Earphone - Grey",
    "sku": "PT-00002",
    "department_id": "2",
    "variants_count": "1",
    "variants": [
        {
            "id": "2",
            "product_id": "2",
            "quantity": "35"
        }
    ],
    "department": {
        "id": "2",
        "name": "Phones & Tabs Accessories"
    }
},
{
    "id": "3",
    "name": "MI In-Ear Headphones Basic 3.5mm HSEJ03JY",
    "sku": "PT-00003",
    "department_id": "2",
    "variants_count": "5",
    "variants": [
        {
            "id": "3",
            "product_id": "3",
            "quantity": "9"
        },
        {
            "id": "4",
            "product_id": "3",
            "quantity": "9"
        },
        {
            "id": "5",
            "product_id": "3",
            "quantity": "10"
        },
        {
            "id": "6",
            "product_id": "3",
            "quantity": "7"
        },
        {
            "id": "7",
            "product_id": "3",
            "quantity": "7"
        }
    ],
    "department": {
        "id": "2",
        "name": "Phones & Tabs Accessories"
    }
}
]

Но я хочу достичь:

[
{
    "id": "2",
    "name": "Letv LU50609 Earphone - Grey",
    "sku": "PT-00002",
    "variants_count": "1",
    "stock": "35",
    "department": "name": "Phones & Tabs Accessories"
},
{
    "id": "3",
    "name": "MI In-Ear Headphones Basic 3.5mm HSEJ03JY",
    "sku": "PT-00003",
    "variants_count": "5",
    "stock": "42",
    "department": "name": "Phones & Tabs Accessories"
}
]

Как мне этого добиться ???

Ответы [ 4 ]

0 голосов
/ 03 ноября 2018

То, что вы ищете, может быть достигнуто разными способами. Идеальное решение будет строить сумму в базе данных для лучшей производительности. Чтобы добиться этого, вы можете использовать пользовательский запрос вместе со сборщиком запросов Laravel, как уже объяснено @nakov, или использовать небольшой эксплойт системы отношений Eloquent:

$products = Product::query()
    ->join('departments', 'departments.id', '=', 'products.department_id)
    ->withCount('variants as variant_count')
    ->withCount(['variants as stock' => function ($query) {
        $query->selectRaw('SUM(quantity)');  // this may look weird but works
    })
    ->select([
        'products.id',
        'products.name',
        'departments.name as department',
    ])
    ->get();
0 голосов
/ 02 ноября 2018

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

 SELECT
    products.*,
    SUM(variants.available) AS stock,
    COUNT(variants.id)  as count,
    department.name as department
FROM
    products
LEFT JOIN variants ON products.id = variants.product_id
LEFT JOIN department ON products.department_id= department.id
GROUP BY
    products.id
0 голосов
/ 02 ноября 2018

Вариант 1

Вы можете map() собрать коллекцию, прежде чем вернуть ее:

  $products = Product::select('id', 'name', 'sku', 'department_id')
        ->withCount('variants')
        ->with(['variants', 'department'])
        ->get()
        ->map(function ($product){
                return [
                    'id'             => $product->id,
                    'name'           => $product->name,
                    'sku'            => $product->sku,
                    'variants_count' => $product->variants_count,
                    'stock'          => $product->variants->sum('quantity'),
                    'department'     => $product->department->name
                ];
            });

Вариант 2

Использование Ресурсов API . Дайте мне знать, если вам нужна помощь в этом аспекте.

0 голосов
/ 02 ноября 2018

Как насчет использования построителя запросов примерно так:

DB::table('products as product')
   ->select([
        'product.id',
        'product.name',
         DB::raw('count(pv.id) as variant_count'),
         DB::raw('sum(pv.quantity) as stock'),
        'department.name'
   ])
   ->join('department', 'product.department_id', '=', 'department.id')
   ->join('product_variants as pv', 'product.id', '=', 'pv.id')
   ->get();

Не уверен, что это будет работать именно так, но это должно дать вам путь.

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