我有一个MySQL表,其中包含客户可以订购的所有可能产品的列表。该表的(非常)简化版本如下所示:
ID | productid | price | age_min | age_max | type
=======================================================================
1 | baseball_1 | 12.34 | 18 | 21 | 1
2 | baseball_2 | 15.99 | 22 | 30 | 1
3 | baseball_3 | 18.99 | 18 | 99 | 1
4 | golf_1 | 4.99 | 18 | 24 | 2
5 | golf_2 | 5.99 | 25 | 44 | 2
6 | tennis_1 | 9.99 | 18 | 50 | 3
7 | tennis_2 | 14.99 | 51 | 99 | 3
在这家商店中,所有产品都经过年龄限制,这意味着如果客户的年龄适合该范围,则客户只能选择要购买的商品。即使每个产品“类型”存在多个选项,自定义也只能选择一个“类型”。在上面的示例表中,24岁的客户只能选择:
baseball_2,baseball_3 golf_1和tennis_1
我正在尝试按已知产品类型组织潜在客户的选项。所以在我的情况下,商店可能会向顾客展示:
我希望使用age变量对数据库进行单个(如果可能)MySQL调用并返回所有可能的产品,然后如上所述相应地显示这些产品。 SQL语句很简单,我已经完成了这个,但我不知道如何循环或构建一个可以列出成员可用选项的正确数组。
可能会建议,但这比显示的要详细得多,并且由于与该问题无关的其他几个因素,使用任何类型的第三方软件或购物车都不是一种选择。这似乎是如何处理多维数组的问题。以前有人遇到过类似的问题吗?
虽然Travesty和tdammer在下面提供的解决方案在某些情况下是有效的,但我希望能够对我的数据做更多的工作,然后只显示它来自我的数据库。页面的布局和设计不应该取决于它在数据库中存储的方式/时间等。有时我可能会先为一组“类型”显示最高价格,而对另一组“最低价格”。
通过使用fetchAll语句,我能够从查询中收集所需的所有必要数据,但我真的不确定如何使用它。例如,我的数组目前是:
Array (
[0] => Array ( [productid] => 394, [price] => 6.20, [type] => 16 ),
[1] => Array ( [productid] => 395, [price] => 12.40, [type] => 16 ),
[2] => Array ( [productid] => 396, [price] => 18.60, [type] => 16 ),
[3] => Array ( [productid] => 397, [price] => 24.80, [type] => 16 ),
[4] => Array ( [productid] => 398, [price] => 31.00, [type] => 16 ),
[5] => Array ( [productid] => 449, [price] => 4.20, [type] => 17 ),
[6] => Array ( [productid] => 450, [price] => 8.40, [type] => 17 ),
[7] => Array ( [productid] => 451, [price] => 12.60, [type] => 17 ),
[8] => Array ( [productid] => 452, [price] => 16.80, [type] => 17 ),
[9] => Array ( [productid] => 453, [price] => 21.00, [type] => 17 )
)
是否有一种很好的方式来构建我自己的数组,以后我可以基本上说“向我展示17型所有项目的产品和价格”?
答案 0 :(得分:3)
您不需要多维数组。
按类型排序查询结果,然后遍历数组。在执行此操作时,在第一个项目之前插入标题,然后在类型更改的每个项目之前插入标题。
如果您有一个正确规范化的数据库,您还应该有一个product_types
表,其中包含您的产品类型ID和名称;在这种情况下,请考虑JOIN
。你的SQL看起来会像这样:
SELECT p.id, p.name, p.price, t.id AS type_id, t.name AS type_name FROM products AS p LEFT JOIN product_types t ON t.id = p.type WHERE :age BETWEEN p.min_age AND p.max_age;
然后,您逐步完成结果集:
$current_type = 'not_a_string';
while ($row = get_next_row_from_database) {
if ($current_type !== $row['type_id']) {
echo '<h3>' . htmlspecialchars($row['type_name']) . '</h3>';
$current_type = $row['type_id'];
}
printf('<p>%s - $%2.2f</p>', htmlspecialchars($row['name']), $row['price']);
}
这种方法使用常量内存(在Web服务器上,显然不在数据库上)和线性时间。
您还应该考虑对数据进行分页:不要一次查询所有行,而是运行COUNT(*)
查询以获取总行数,然后使用LIMIT
获取只有当前页面的行(您可能还想指定一个ORDER BY
子句以使您的页面有意义。)
答案 1 :(得分:3)
我认为你不需要多维数组。我认为你只需要遍历你的行并在你来到一个新组时改变你的标题。
我对这个答案采用了一种不同的方法,将每一行粘贴到一个数组中,然后将它们内爆,以便保留格式。
//USING PDO - assume connection already made
/* added ORDER BY in the query to ensure that we get the rows sequentially, by type */
$stmt = $db->prepare("SELECT * FROM table WHERE age_min >= :age AND age_max <= :age ORDER BY type");
$stmt->bindParam(":age", $customer_age);
$stmt->execute();
$type = -1;
$lines = array();
while ($data = $stmt->fetch(PDO::FETCH_ASSOC))
{
$data = array_map("htmlspecialchars", $data); /* sanitize data for HTML output */
if ($type != $data["type"])
{
$type = $data["type"];
list($typeName) = explode("_", $data["productid"]); /* this assumes that you don't have a column with the actual product name. If you do, use that instead. */
$lines[] = (count($lines) > 0 ? "</ul>\n" : "") ."<h2>". ucfirst($typeName) ." Option</h2>\n<ul>";
}
$lines[] = "\t<li>{$data["productid"]} - {$data["price"]}</li>";
}
echo implode("\n", $lines) ."\n</ul>";
<小时/> 对问题更新的回复:
是否有一种很好的方式来构建我自己的数组,以后我可以基本上说“向我展示17型所有项目的产品和价格”?
这是一个查询。我仍然认为没有理由将它存储在一个数组中。如果您想获得类型为17的所有项目的产品和价格,那么您应该在数据库上执行该查询。如果您想以不同方式订购结果,则应更改ORDER BY
条款。
也许您需要调整查询以使其更灵活:
if (!isset($_POST["columns"]))
$_POST["columns"] = "productid, price";
if (!isset($_POST["whereClause"]))
$_POST["whereClause"] = "TRUE";
if (!isset($_POST["orderby"]))
$_POST["orderby"] = "type ASC, price DESC";
$stmt = $db->prepare("SELECT :columns FROM table WHERE age_min >= :age AND age_max <= :age AND :whereClause ORDER BY :orderby");
$stmt->bindParam(":columns", $_POST["columns"]);
$stmt->bindParam(":age", $customer_age);
$stmt->bindParam(":whereClause", $_POST["whereClause"]);
$stmt->bindParam(":orderby", $_POST["orderby"]);
$stmt->execute();
您可以使用HTML表单提交(导致页面重新加载)来调用它,也可以通过AJAX调用它。但无论哪种方式,我都没有看到如何做一个fetchAll
并将结果存储在数组中对你有什么好处。
答案 2 :(得分:1)
根据数据库的大小,此解决方案可能无法正常工作,但通常我的工作方式是:
将数据库结果循环到我的设计数组中
所以我可能有
Array['baseball'][0]['price'] = 15.99
Array['baseball'][1]['price'] = 18.99
遍历我创建的数组以解析结果。
在较大的数据库中,您需要一个不同的解决方案,因为这会让您多次循环结果...