2016-08-13 3 views
0

Я зацикливаюсь на использовании запросов функций SQL, сделанных в CakePHP 3, в комбинациях с ассоциациями.CakePHP 3.x - SUM() на ManyToMany

Ситуация такова: у меня есть три таблицы, таблица «продукты», таблица «заказы» и таблица соединений, называемая «orders_products».

В индексе OrdersController я хотел бы добавить общую цену (= сумму соответствующих цен на товары) в таблицу заказов. В SQL это точно можно сделать с помощью следующего запроса:

SELECT orders.id, SUM(products.price) 
FROM orders 
LEFT JOIN orders_products 
ON orders.id = orders_products.order_id 
LEFT JOIN products 
ON orders_products.product_id = products.id 
GROUP BY orders.id; 

Я вычислял на следующий код контроллера должен сделать трюк:

$orders = $this->Orders->find('all')->contain(['Products']); 

$orders 
     ->select(['total_price' => $orders->func()->sum('Products.price')]) 
     ->group('Orders.id'); 

Однако, когда объект запроса выполняется, я получаю сообщение об ошибке :

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Products.price' in 'field list'

... Даже если определена связь между заказами и продуктами.

Вызов только $orders = $this->Orders->find('all')->contain(['Products'])->all(); действительно возвращает массив заказов с каждым заказом на ряд продуктов, модель должна быть настроена правильно. Какие-нибудь идеи, что может быть неправильным? Заранее спасибо!

От OrdersTable:

$this->belongsToMany('Products', [ 
    'foreignKey' => 'order_id', 
    'targetForeignKey' => 'product_id', 
    'joinTable' => 'orders_products' 
]); 

И от ProductsTable:

$this->belongsToMany('Orders', [ 
     'foreignKey' => 'product_id', 
     'targetForeignKey' => 'order_id', 
     'joinTable' => 'orders_products' 
    ]); 

ответ

2

Один из способов сделать это:

$orders = $this->Orders->find() 
    ->select([ 
     'order_id' =>'orders.id', 
     'price_sum' => 'SUM(products.price)' 
    ]) 
    ->leftJoin('orders_products', 'orders.id = orders_products.order_id'), 
    ->leftJoin('products', 'orders_products.product_id = products.id') 
    ->group('orders.id'); 
+0

Спасибо, это работает. Однако не странно ли вы вручную использовать таблицу соединений? Разве это не функция '-> содержать' и модели? Я имею в виду, что указана таблица соединений и соответствующие поля. – Roberto

+0

В зависимости от отношения между таблицами, 'содержать' может вызвать объединение, или это может вызвать выпуск второго запроса после завершения первого. В последнем случае вам нужно принудительно объединить соединение, если ваш запрос зависит от всех таблиц, на которые делается ссылка в одном запросе. –

+0

Благодарим вас за разъяснение. По-прежнему кажется немного произвольным, какой подход необходим. – Roberto