質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

DBからデータを受け取れない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 770

YukaSaku

score 41

小さな ECサイトのカート部分で、ユーザーが商品を選んだ際にその商品情報をDBに取りに行って、ユーザーがドロップダウンから選択した商品個数とともに、表示をしたいと思っています。
商品が選ばれた時(product_get.php)に、DBに見にいく(cart.inc)ようにしています。

結果は以下のように表示されます。

array(1) { [0]=> array(1) { ["item"]=> NULL } } 1

なぜ、中身が入ってこないのでしょうか。
cart.incのSELECT文実行後がよくないんだろうなぁと思ってるのですが、どう直していいのかわかりません。よろしくお願いします。

以下に、使っているプログラムを載せます。

<?php
//product_get.php//
session_start();
ini_set("display_errors","on");
error_reporting(E_ALL | E_STRICT);
ini_set("include_path","./includes");
include("dbinfo.inc");
$quantity = 0;
?>
<!DOCTYPE>
<HTML>
<HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Ex6 Sofa</title>
  <link rel="stylesheet" href="custom.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
</HEAD>
<BODY>
  <div class="col-xs-6 col-xs-offset-3">
          <h1>Online shop</h1><p>Hi, <?php echo $_SESSION['username']; ?>!!</p><p>Customer ID:<?php echo $_SESSION['cust_id']; ?></p>
                    <?php
                    if(!isset($_SESSION['catalog_id'])) {
                    ?>
                    <dl class="cart">
                        <dd>Quantity of items:<?php print $quantity; ?></dd>
                        <form action="cartcontent.php" method="post">
                      <input type="hidden" item="cart" value="<?php print$quantity; ?>" name="cart" />
                     <input value="See Cart" type="submit">
                    </form>
                  </dl>
<?php
}
{
  // データベースに接続
  $dbLink = mysqli_connect($host, $user, $passwd, $dbname);

  // Get product info
  $sql = "SELECT pd.catalog_id, pd.name, pd.description, pd.price, pd.category_id,
    pi.path, pi.path_small FROM product_discription pd, product_img pi
    WHERE pi.catalog_id = pd.catalog_id
    AND pi.category_id = " . $_POST['category'];

  $result = mysqli_query($dbLink, $sql) or trigger_error(mysqli_error($dbLink));

  $itemfc = "";
  while ($item = mysqli_fetch_array($result)) {
?>
    <dl class="products">
            <dd><a href="item_detail.php?product_id=<?echo $item['catalog_id'] ?>"><?php print($item['name']); ?></a></dd>
      <dd>Category:<?php print($item['category_id'] ); ?></dd>
      <dd>Catalog ID:<?php print($item['catalog_id'] ); ?></dd>
      <dd>Price:$<?php print($item['price'] ); ?>CAD</dd>
      <dd>Description:<?php print($item['description'] ); ?></dd>
      <dt><img src="furniturestore/<?php print($item['path_small'] ); ?>" alt="" /></dt>
    </dl>
    <form action="cart.php" method="post">
      <select name="num">
        <?php
          for ($i = 1; $i <= 9; $i++) {
    echo "<option value='" . $i . "'>".$i."</option>";
        $quantity = $i;
          }
        ?>
      </select>
      <input type="hidden" name="act" value="add">
      <input type="hidden" name="itemToAdd" value="<?php echo $item['catalog_id'] ?>">
      <input type="submit" name="submit" value="Go to Cart">
    </form>
<?php
}
mysqli_free_result($result);
 }
?>
        </div>
        </body>
        </html>
<?php
//add.php//
ini_set("display_errors","on");
error_reporting(E_ALL | E_STRICT);
ini_set("include_path","./includes");
include("cart.inc");
session_start();
$cart = new Cart();


?>
<!DOCTYPE>
<HTML>
<HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Ex6 Add</title>
  <link rel="stylesheet" href="custom.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
</HEAD>
<BODY>
  <div class="col-xs-6 col-xs-offset-3">

<form action="cartcontent.php" method="post">
    <?php
        $items =$cart->getAll();
        var_dump($items);
        print_r(count($items));

        foreach ($cart->getAll() as $item) {
            echo "added" . $item['quantity'] . " " . $item['item']['name'];
        }
    ?>
    <input type="hidden" item="cart" value="" name="cart" />
 <input value="See Cart" type="submit">
</form>
<?php
//cart.php//

ini_set("display_errors","on");
error_reporting(E_ALL | E_STRICT);
ini_set("include_path","./includes");
include("dbinfo.inc");
include("cart.inc");
session_start();
// 指定されたリクエストパラメータを取得する
function getRequestValue($key, $default=null)
{
    if (isset($_REQUEST[$key])) {
        // 存在するときはリクエストパラメータを返す
        return $_REQUEST[$key];
    } else {
        // 存在しないときはデフォルト値を返す
        return $default;
    }
}
$do ="";
$cart = new Cart();

if (isset($_POST['itemToAdd'])) {
$qty = ($_POST['quantity']); //rename to the form value name in product_get
$act = getRequestValue('act','cart'); // アクションを取得
switch ($act) {
case 'add': // 追加
    $item = $_POST['itemToAdd'];
    if (!is_null($item)) {
        $cart->addItem($item,$qty);
        $do = "add.php";
    } else {
        $do = "loggedin.php";
    }
    break;
case 'cart': // 中身を表示
    $item = $cart->getAll();
    $do = "cartcontent.php";
    break;
case 'remove': // 削除
    $catalog_id = $_REQUEST($_POST['catalog_id']);
    if (!is_null($_POST['cart'])) {
        include(cart_empty.php);
    }
    $item = $_POST['cart']->getAll();
    $do = "cartcontent.php";
    break;
case 'order': // 注文
    $cart->removeAll();
    $do = "order.php";
    break;
default: // (存在しない動作)
    echo "What's up?";
    exit;
    break;
}
}
header("Location: " . $do)
//include($do);
?>
<?php
//cart.inc//
include("dbinfo.inc");
class Cart {
    function __construct() {
        if (!array_key_exists('cart', $_SESSION)) {
            $_SESSION['cart'] = array();
        }
    }
    // カートの中身を取得する
    function getAll() {
        return $_SESSION['cart'];
    }
    // カートに商品を追加する
    function addItem($item, $quantity) {
        $id = $item;
        if(!isset($_GET['catalog_id'])) {
        $dbLink = mysqli_connect($host, $user, $passwd, $dbname);
        $sql = "SELECT pd.catalog_id, pd.name, pd.description, pd.price, pd.category_id,
          pi.path FROM product_discription pd, product_img pi
          WHERE pi.catalog_id = pd.catalog_id
          AND pd.catalog_id = " . $id;
        }
        $result = mysqli_query($dbLink, $sql) or trigger_error(mysqli_error($dbLink));
        if (isset($_SESSION['cart'][$this->numberOfItems()]['id'])) {
            // 注文数を増やす
            $_SESSION['cart'][$this->numberOfItems()]['item'] = $items; //TODO: Item returned from db;
            $_SESSION['cart'][$this->numberOfItems()]['quantity'] += $_POST['num']; //TODO: Item returned from db;
        }
        else { //新規注文
          $_SESSION['cart'][$this->numberOfItems()]['item'] = $items;
        }
    }
    // カートから商品を取り除く
    function removeItem($catalog_id) {
        unset($_SESSION['cart'][$catalog_id]);
    }
    // カートを空にする
    function removeAll() {
        $_SESSION['cart'] = array ();
    }

    function getItem($index) {
        return $_SESSION['cart'][$index];
    }

    function numberOfItems() {
        return count($_SESSION['cart']);
    }
}
?>


テーブルは以下の通りになります。(table名はdiscriptionとスペルを間違えてますが、直せなかったのでこれでやってます)
Table Name: product_discription

Column Name Type Description
catalog_id INT(5) Customer ID number.AUTO_INCREMENT. Primary key.Unique.
name     VARCHAR(50) Product name.
description VARCHAR(500) The description of product.
price     DECIMAL(7,2) The price of product.
category_id INT(5) The category ID of product.

Table Name: product_category

Column Name Type Description
category_id INT(5) Category ID number.AUTO_INCREMENT. Primary key.Unique.
category VARCHAR(100) The name of the category.

Table Name: product_img

Column Name Type Description
catalog_id INT(5) Catalog ID number.AUTO_INCREMENT. Primary key.Unique.
path VARCHAR(300) the small picture path.
path_small VARCHAR(300) the picture path.
category_id INT(5) Category ID number.
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

SQL文に、直接$_POST['category']を連結するのが危険。
SQLインジェクションってわかりますか。

$_POSTで受け取ったパラメータをもっと丁寧に点検しないと、
構造がわかってしまえばあっさり蹂躙されますよ。

それはそれとして、POSTでパラメータを送っていないときに
そのページを表示させると、$_POST['category']が未定義になります。
そうすると不完全なSQL文を実行してしまうため、SQL文実行で文法エラーが返されて、
クエリー結果を得ようとしても出来ません。
$_POST['category']があるときとないとき
(正確に言うと、さらにクエリー結果が得られたかどうか、でも分岐が必要)で条件分岐が絶対必要です。
URLで「~&category=1」とかやっているのだとすると、それは$_GET['category']ですので、
$_POST['category']には入ってきません。

以下、余談。

それと、catalog_idが主キーと思われるテーブルが二つあって、
それぞれでオートインクリメントしてるのって、
意図しないidのズレを生じたりしないか心配になります。

また、
product_discription 1に対して、product_img も1なのかな、
商品画像は複数ありえないのかも心配な点。

コードをまるっと示されてもさすがにこちらでテスト実行できるほど余裕が無いので、
直接の解決方法に至ってないかもしれない点はご容赦ください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/29 04:29

    沢山問題点を上げていただきありがとうございます。一つ一つ潰して行きました。
    またコードを書くときに注意しないといけない点もすごく参考になりました。
    SQLインジェクションはどんなものかは知っていますが、どうするとどうされるとか、こうすれば避けられるとかは全くわかっていません。コードが雑なのですね。
    ”意図しないidのズレ”というのが、私もすごく気になったのですが、学校側がそうしなさいというので、今回はこのように作っています。画像複数というのも将来は気にしないといけないですね。

    雑なコードに一つ一つメスを入れ、持ってきたデータの配列も雑でしたが、DBからデータを持ってくることはできたので、こちらをベストアンサーにさせていただこうと思います。
    ありがとうございます。

    キャンセル

  • 2017/06/29 06:07

    すみません。既にベストアンサーを選ばせていただいて、DBからデータを持ってくることができたを書いたのですが。。。
    なぜかDBに繋げることが出来ておらず、include("dbinfo.inc");の中身、$host =、$user =、$passwd =、$dbname =を直接書いたら、繋げることが出来て、DBのデータを持ってくることが出来た感じです。

    このinclude("dbinfo.inc");の中身は、他でも使っているので間違っていないと思うのですが、cart.inc内の書き方で何か間違っているでしょうか??

    キャンセル

  • 2017/06/29 09:37

    PHP: include - Manual <http://php.net/manual/ja/function.include.php>
    include_path に定義されているディレクトリ上に dbinfo.inc なるファイルが存在しない、ということはありませんか? ファイルの置いてある場所まで、実行するphpファイルの場所から相対パスで指定しても良いかもしれません。
    あと、(テスト含め)実行した際のwebサーバーの access.log や error.log はチェックできているでしょうか。サーバーの設定上、webブラウザ側に対してエラー情報をあまり示さない設定だとしても、 error.log にはエラー情報を出力しているでしょうから、ログを確認して、エラーメッセージを検索すればヒントは見つかります。

    キャンセル

  • 2017/06/30 13:05

    早速コメントいただきありがとうございます。
    ログ、確認してみます。

    キャンセル

+1

ちょっと動きがよく分からないのですが、
まずは $_POST['category'] に値が
入ってるか確認するのかなあ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/28 09:15

    ありがとうございます。$_POST['category']、確認してみます。

    キャンセル

0

動きが良く見えません(私だけ?)
product_get.phpにはどこから遷移しているのでしょう?
あとcategory_idが各テーブルで型が異なるのが気になりました。
まずは$_POST['category']に想定した値が入っていることを確認。
あとは生成しているクエリが単体で実行した場合にきちんと動くのかを確認でしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/28 09:14

    本当に見事にcategory_idの型が違ってました。ここに載せるときに間違えたのかと思ったら、本当にDBの方もそうなってて、早速直しました。
    $_POST['category']、確認してみます。ありがとうございます。

    キャンセル

  • 2017/06/28 10:37

    catalog_id INT(5)とcategory_id INT(10)の混同がこわいコーディングですね。

    キャンセル

  • 2017/06/28 22:10

    確かにそうですね。かなり混同しています。直します。ありがとうございます。

    キャンセル

  • 2017/06/29 00:11

    これらのプログラムの前にログイン画面があり、login.php -> loggedin.php -> product_get.phpという感じで遷移してきています。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる