Есть структура данных в базе
product1 category2
product2 category1
product3 category1
product4 category3
....
Мне необходимо вывести эти данные в select и сгруппировать с помощью optgroup, чтобы по итогу было как то так
-category1
--product2
--product3
-category2
--product1
-category3
--product4
Я в целом смог сделать подобный вывод
$STH = $DBH->query('SELECT * from product');
$STH->setFetchMode(PDO::FETCH_ASSOC);
$current_category = null;
while($row = $STH->fetch()) {
if ($row["p_category"] != $current_category) {
$current_category = $row["p_category"];
echo "#{$current_category}";
}
echo "<p>{$row["p_name"]} </p>";
}
Но в данном случае я не могу управлять группой,чтобы заключить ее в <optgroup>, так как я отдельно управляю названиями продукта и названиями категорий, а как сделать,чтобы можно было заключить отдельные группы в <optgroup> ?
Достаточно сортировку добавить в запрос и дополнить условия вывода:
$STH = $DBH->query('SELECT * from product ORDER BY p_category, p_name');
$STH->setFetchMode(PDO::FETCH_ASSOC);
$current_category = null;
echo '<select>';
while($row = $STH->fetch()) {
// новая группа
if ($row['p_category'] !== $current_category) {
// предыдущую группу закрыть
if ($current_category !== null) {
echo '</optgroup>';
}
$current_category = $row['p_category'];
echo '<optgroup label="' . $current_category . '">';
}
echo '<option value="' . $row['p_name'] . '">' . $row['p_name'] . '/option>';
}
// предыдущую группу закрыть
if ($current_category !== null) {
echo '</optgroup>';
}
echo '</select>';
Если сгруппировать по категориям и воспользоваться GROUP_CONCAT для объединения продуктов для категории, то может получится что-то такое
$STH = $DBH->query('SELECT `p_category`, GROUP_CONCAT(p_name) as `products`
FROM `product`
GROUP BY `p_category`'
);
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
$current_category = $row["p_category"];
$products = explode(',', $row["products"]); // <!---- в $products будет массив продуктов
echo "#{$current_category}";
// здесь в цикле можно пробежаться по $products
foreach ($products as $p_name) {
echo "<p>$p_name</p>";
}
}
в итоге в p_category - будет имя категории, а в products - будут через запятую перечислены имена продуктов. Это перечисление можно разбить через explode
Хотел было пойти спать, но когда увидел данный вопрос (даже с имеющимися рабочими ответами) - просто не смог. От чудовищной несправедливости - как будто весь мир сговорился и решил просто игнорировать само существование чудесной константы PDO::FETCH_GROUP, словно созданной специально для этой задачи.
Собсно решение с применением потрясающей константы PDO::FETCH_GROUP:
$STH = $DBH->query('SELECT `p_category`, `p_name` FROM `product`');
echo '<select>';
foreach($STH->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_COLUMN) as $pcategory => $pnames) {
echo "<optgroup label=\"$pcategory\">";
foreach($pnames as $pname) {
echo "<option value=\"$pname\">$pname</option>";
}
echo "</optgroup>";
}
echo '</select>';
P.S. если вдруг понадобятся какие-то другие штуки, кроме p_name, тогда надо будет заменить fetchStyle на PDO::FETCH_GROUP | PDO::FETCH_ASSOC - ну и соответственно изменить подстановку значения в html-строку.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости