Многие ко многим. MySQL + PHP
В базе есть таблицы product, product_category, category. В product_category две колонки product_id и category_id Задача получить все товары и чтобы у каждого товара был массив категорий.
Пытаюсь достать в модели так, но получаю дублирование товаров, т.к. у них несколько категорий:
class Product
{
private $pdo;
public function __construct()
{
$this->pdo = DB::instance();
}
public function findAll()
{
$sql = "SELECT product.id, product.name, product.price, product_category.category_id
FROM product, product_category
WHERE product_category.product_id = product.id";
return $this->pdo->query($sql);
}
public function lastInsertId()
{
return $this->pdo->lastInsertId();
}
}
Получаю это дело в контроллере:
public function indexAction()
{
$model = new Product();
$products = $model->findAll();
render('main/index', [
'products' => $products
]);
}
В PDO пробовал PDO::FETCH_ASSOC и PDO::FETCH_OBJ. Возможно ли это сделать одним SQL запросом или нужно под каждым товаром еще раз SQL запрос писать? Может как-то собрать массив категорий у товара можно? Никак не получается! Заранее спасибо!
Ответы (2 шт):
Автор решения: Аксенов Максим Александрович
→ Ссылка
Решил пока так:
public function findAll()
{
$sql = "SELECT product.id, product.name, product.price,
product_category.category_id
FROM product, product_category
WHERE product_category.product_id = product.id";
return $this->pdo->query($sql);
}
public function findAllWithCategory() {
$products = $this->findAll();
$id = $products[0]['id'];
$tree[$id]['id'] = $products[0]['id'];
$tree[$id]['name'] = $products[0]['name'];
$tree[$id]['price'] = $products[0]['price'];
foreach ($products as $product) {
if ($product['id'] == $id) {
$tree[$product['id']]['category'][] = $product['category_id'];
} else {
$tree[$product['id']]['id'] = $product['id'];
$tree[$product['id']]['name'] = $product['name'];
$tree[$product['id']]['price'] = $product['price'];
$tree[$product['id']]['category'][] = $product['category_id'];
}
}
return $tree;
}
Выглядит массивно) Может есть возможность короче?
Автор решения: ArchDemon
→ Ссылка
Дополню ответ Максима. Упростить можно:
public function findAllWithCategory() {
$products = $this->findAll();
$tree = [];
foreach ($products as $product) {
if (!array_key_exists($product['id'], $tree)) {
$tree[$product['id']] = array_intersect_key($product, array_flip(['id', 'name', 'price']));
}
$tree[$product['id']]['category'][] = array_intersect_key($product, array_flip(['category_id']));
}
return $tree;
}