0

顧客が注文できるすべての可能な製品のリストを含む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

この店では、すべての商品に年齢制限があります。つまり、顧客は自分の年齢がその範囲内に収まる場合にのみ、購入する商品を選択できます。カスタムは、製品の「タイプ」ごとに複数のオプションが存在する場合でも、1つの「タイプ」のみを選択できます。上記の表の例では、24歳の顧客は以下を選択することしかできません。

baseball_2、baseball_3 Golf_1、tennis_1

私は、潜在的な顧客が持つオプションを、既知の製品タイプ別に整理してレイアウトしようとしています。したがって、私の場合、ストアは顧客に次のように表示する場合があります。

野球オプション

  • baseball_2-$ 15.99
  • baseball_3-$ 18.99

ゴルフオプション

  • Golf_1-4.99ドル

テニスオプション

  • Tennis_1-$ 9.99

年齢変数を使用してデータベースに対して単一の(可能であれば)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のすべてのアイテムの製品IDと価格を表示してください」と言うことができる方法で独自の配列を構築する良い方法はありますか?

4

3 に答える 3

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のすべてのアイテムの製品IDと価格を表示してください」と言うことができる方法で独自の配列を構築する良い方法はありますか?

それはクエリです。それを配列に格納する理由はまだわかりません。タイプ17のすべてのアイテムの製品IDと価格を取得する場合は、データベースでそのクエリを実行する必要があります。結果の順序を変えたい場合は、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しかし、いずれにせよ、結果を配列に格納することで、どのように効果があるのか​​わかりません。

于 2012-05-08T19:10:57.593 に答える
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ページを意味のあるものにする句を指定します)。

于 2012-05-08T19:02:17.967 に答える
1

データベースのサイズによっては、このソリューションが機能しない場合がありますが、一般的に、小規模での作業方法は次のとおりです。

データベースの結果を私のデザインの配列にループします

だから私は持っているかもしれません

Array['baseball'][0]['price'] = 15.99
Array['baseball'][1]['price'] = 18.99

結果を解析するために作成した配列をループします。

大規模なデータベースでは、結果の結果を複数回ループさせるため、別のソリューションが必要になります...

于 2012-05-08T18:57:38.903 に答える