【问题标题】:Order headings in list of items from MySQL DB with PHP使用 PHP 在 MySQL DB 中的项目列表中排序标题
【发布时间】:2020-04-18 05:19:19
【问题描述】:

希望有人知道查询/处​​理这些标题的好方法...

例如,如果您有一个食谱,它可能如下所示:(带有标题和成分)


沙拉
  • 新鲜生菜
  • 切碎的胡萝卜
  • 新鲜草莓

着装

  • 肉桂

装饰

  • 杏仁片

在 MySQL 数据库中,我将把这些数据存储在 recipe 表中。所以这个食谱可能看起来像这样:

+----+---------------+-----------------+--------------------+---------------------+-----------+---------+-----------+---------+-----------+---------+
| id | ingredient_1  |  ingredient_2   |   ingredient_3     | ingredient_4 etc... | heading_a | h_a_pos | heading_b | h_b_pos | heading_c | h_c_pos |
+----+---------------+-----------------+--------------------+---------------------+-----------+---------+-----------+---------+-----------+---------+
|  1 | Fresh Lettuce | Chopped carrots | Fresh Strawberries | Vinegar             | Salad     |       1 | Dressing  |       4 | Garnish   |       7 |
+----+---------------+-----------------+--------------------+---------------------+-----------+---------+-----------+---------+-----------+---------+

配料全部存放在一起,标题存放在一起。 (不同的菜谱需要不同的标题和与配料相关的不同位置。)这里的标题位置(h_a_pos等)表示配料#以在前面列出标题。

当涉及到查询这个来显示它时,如果我运行一个简单的 SQL 查询:

SELECT * FROM recipes WHERE id = 1;

这只会返回给我所有内容的列表。这是一个 SQL Fiddle:http://sqlfiddle.com/#!9/942d8a3/1/0

使用 PHP,我可以获取结果并将其放入数组中。而且我确信有某种方法可以对它们进行排序,但我正在画一个空白......

$response = []; // blank array
$sql_retrieve = $con->prepare("SELECT * FROM recipes WHERE id = 1");
$sql_retrieve->execute();
$result = $sql_retrieve->get_result(); 
if($result->num_rows>0){
  while($row=$result->fetch_assoc()){
    $response[] = $row;
  } // end of while
} // end of num_rows

print_r($response); // display response pre-sorting

// sort array -- not working
usort($response, function($a, $b) {
  return $a['h_a_pos'] <=> $b['h_b_pos'];
});

// would need something to order it in relation to the ingredients...

echo '<br /><br />';
print_r($response); // display response post-sorting

我可以更改数据库结构,但如果可能的话,我更愿意将其保留在一个表中。 (我知道有些成分可能没有标准化,但我也没有在这个例子中列出数量等。)

有人对如何存储标题有任何想法吗?我基本上只需要知道它应该是一个标题(因此可以适当地格式化),文本应该是什么,以及在哪个成分编号之前显示它。 (我永远不会查询标题,所以如果这可以更好地序列化存储,那可能是一个选择......)

【问题讨论】:

  • 这是一个糟糕的数据库结构。在继续之前了解标准化。
  • 例如,如果某些食谱没有第三种成分,则该列中的值为空。您最好创建一个 1:n 关系,例如1 个配方有很多成分或 1 个配方有很多类别,而 1 个类别有很多成分。类别是标签沙拉,装饰等
  • 因此,如果我有另一个表格用于成分,另一个用于链接它们的表格(recipe_ingredients)和另一个用于配方标题的表格;关于如何以正确的顺序排列标题,这仍然没有让我更进一步......
  • 使用 GROUP_CONCAT() 而不是旋转将多种成分放入多个列中。

标签: php mysql database-design


【解决方案1】:

你得到的不是normal。例如,如果您决定想要一个复杂的配方,其中成分多于列,或者成分标题多于列,您就会遇到麻烦。要吸取的重要教训是,数据库不是电子表格。

这里有一些更接近您想要的数据库结构的东西:

CREATE TABLE categories (id SERIAL, name VARCHAR(32));
CREATE TABLE ingredients (id SERIAL, category_id BIGINT UNSIGNED NOT NULL, name VARCHAR(32));
CREATE TABLE recipes (id SERIAL, name VARCHAR(32));
CREATE TABLE ingredients_recipes (recipe_id BIGINT UNSIGNED NOT NULL, ingredient_id BIGINT UNSIGNED NOT NULL);

显然,您还需要一些外键约束来强制表之间的链接,但我们将在此处跳过。用你的成分填充它:

INSERT INTO categories VALUES (1, 'Salad'), (2, 'Dressing'), (3, 'Garnish');
INSERT INTO ingredients VALUES (1, 1, 'Fresh Lettuce'), (2, 1, 'Chopped Carrots'), (3, 1, 'Strawberries'), (4, 2, 'Balsamic Vinegar'), (5, 2, 'Olive Oil'), (6, 3, 'Sliced Almonds');
INSERT INTO recipes VALUES (1, 'My Salad');
INSERT INTO ingredients_recipes VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6);

现在,可以使用简单的连接来提取完整​​的配方:

SELECT r.name AS recipe, c.name AS category, i.name AS ingredient
FROM ingredients i
LEFT JOIN categories c ON (i.category_id = c.id)
LEFT JOIN ingredients_recipes ON (ingredient_id = i.id)
LEFT JOIN recipes r ON (recipe_id = r.id)
WHERE r.id = ?
ORDER BY c.id ASC

这里有一个小提琴来说明这一点:http://sqlfiddle.com/#!9/aecbbd/1

(请注意,“标题”的顺序必须在创建时单独定义。在这种情况下,我只是按 ID 排序。)

现在,在您的 PHP 中,您可以轻松地执行此查询并按类别对成分进行分组:

$stmt = $con->prepare($query);
$stmt->bind_param("i", $recipe_id);
$stmt->execute();
while ($row = $stmt->fetch_assoc()) {
    $name = $row["recipe"];
    $ingredient_types[$row["category"]][] = $row["ingredient"];
}

在显示期间,只需循环遍历数组:

<h1>How to make <?= $name ?></h1>
<?php foreach($ingredient_types as $category=>$ingredients): ?>
    <h2><?= $category ?></h2>
    <ul>
    <?php foreach ($ingredients as $ingredient): ?>
        <li><?= $ingredient ?></li>
    <?php endforeach ?>
    </ul>
<?php endforeach ?>

您的问题提到了数量,这些将作为附加列存储在数据透视表ingredients_recipes 中,并且可以轻松地拉入SELECT 子句中。

【讨论】:

  • 欣赏它,迈克!我可能会将要链接的类别从 components_recipes 表中移出,因为根据配方的不同,一种成分可能属于不同的类别。现在要弄清楚当配方被输入数据库时​​如何建立接口和建立所有这些连接的代码...... :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 2014-04-28
  • 1970-01-01
  • 2012-03-20
  • 2014-10-12
相关资源
最近更新 更多