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

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

ただいまの
回答率

88.77%

MySQL:DB上にアップロードした画像をWeb上に画像として表示したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,111

wataaame

score 13

PHPを使って下記の画像のような商品管理画面を作りたいと思っています。
イメージ説明

DBはMySQLを使用しています。

現在、下のようにコードを書いていて新規商品追加の画面までは、
作成できたのですがファイルを選択し商品を追加してもアップロードした画像が画像として表示されず、
画像のファイル名が表示されてしまいます。
下から7行目のforeach文の引数が違うのかなと思うのですが、
他の変数で試行錯誤しましたができませんでした。
どこのコードを訂正すれば良いかわからず困っています。
初心者のため拙いコードになっていますが、訂正箇所を教えていただけませんか。よろしくお願いいたします。

<?php

$drink_name = '';
$price = '';
$error = array();
$data = "";
$host = 'localhost';
$username = '';
$password ='';
$dbname = '';
$charset = 'utf8';
$img = '';
$value = '';
$img_dir    = './img/';    // アップロードした画像ファイルの保存ディレクトリ
$data       = array();
$err_msg    = array();     // エラーメッセージ
$new_img_filename = '';   // アップロードした新しい画像ファイル名

if ($_SERVER['REQUEST_METHOD'] === 'POST' ) {
    if (isset($_POST['drink_name'])) {
        $drink_name = $_POST['drink_name'];
    }
    if (isset($_POST['price'])) {
        $price = $_POST['price'];
    }
    if ($drink_name === '') {
        $error[] = 'ドリンク名を入力してください。';
    }
    if ($price === '') {
        $error[] = '値段を入力してください。'; 
    }
}
var_dump ($_FILES);
var_dump($drink_name);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  // HTTP POST でファイルがアップロードされたかどうかチェック
  if (is_uploaded_file($_FILES['file_select']['tmp_name']) === TRUE) {
    // 画像の拡張子を取得
    $extension = pathinfo($_FILES['file_select']['name'], PATHINFO_EXTENSION);
    // 指定の拡張子であるかどうかチェック
    if ($extension === 'jpg' || $extension === 'jpeg') {
      // 保存する新しいファイル名の生成(ユニークな値を設定する)
      $new_img_filename = sha1(uniqid(mt_rand(), true)). '.' . $extension;
      // 同名ファイルが存在するかどうかチェック
      if (is_file($img_dir . $new_img_filename) !== TRUE) {
        // アップロードされたファイルを指定ディレクトリに移動して保存
        if (move_uploaded_file($_FILES['file_select']['tmp_name'], $img_dir . $new_img_filename) !== TRUE) {
            $err_msg[] = 'ファイルアップロードに失敗しました';
        }
      } else {
        $err_msg[] = 'ファイルアップロードに失敗しました。再度お試しください。';
      }
    } else {
      $err_msg[] = 'ファイル形式が異なります。画像ファイルはJPEGのみ利用可能です。';
    }
  } else {
    $err_msg[] = 'ファイルを選択してください';
  }
}

$dsn = 'mysql:dbname='.$dbname.';host='.$host.';charset='.$charset;
$dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

if (count($error) === 0 && isset($_POST['submit'])) {
    try {
        $datetime = date("Y-m-d H:i:s");

        $sql = 'INSERT INTO `test_drink_master`(`drink_name`, `price`, `img`,`create_datetime`) VALUES (?,?,?,?)';
        $stmt = $dbh->prepare($sql);
        $stmt->bindValue(1, $drink_name, PDO::PARAM_STR);
        $stmt->bindValue(2, $price, PDO::PARAM_STR);
        $stmt->bindValue(3, $new_img_filename, PDO::PARAM_STR);
        $stmt->bindValue(4, $datetime, PDO::PARAM_STR);
        $stmt->execute();
    } catch (PDOexception $e) {
        echo '接続できませんでした。理由:'.$e->getMessage();
    }
}

try{
    $sql ='select drink_name,price,img,create_datetime from test_drink_master';
    $stmt = $dbh->prepare($sql);
    $stmt->execute(null);
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $data .= "<p>".$row['create_datetime']." ".$row['drink_name']." ".$row['price']." ".$row['img']."</p>";
    }
} catch(PDOException $e) {
    echo '接続できませんでした 理由:'.$e->getMessage();
}
?>

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>自動販売機管理ツール</title>
    </head>
    <body>
        <h1>自動販売機管理ツール</h1>
        <hr>
        <?php if(count($error) > 0) { ?>
        <?php foreach ($error as $value) { ?>
            <?php echo "<p>".$value."</p>" ?>
        <?php } } ?>
        <form method = "post" enctype="multipart/form-data">
            <h2>新規商品追加</h2>
            名前:<input type="text" name="drink_name" size="20"><br>
            値段:<input type="text" name="price" size="20"><br>
            <input type="file" name="file_select" value="ファイルを選択"><br>
            <input type="submit" name="submit" value="商品を追加"><br>
        </form>
        <hr>
        <h2>商品情報変更</h2>
        <p>商品一覧</p>
        <?php echo $data?>
        <table>
            <tr>
              <th>画像</th>
            </tr>
        <?php foreach ($new_img_filename as $img)  { ?>
          <tr>
            <td><img src="<?php echo $img_dir . $value['img_file_name']; ?>"></td>
          <tr>
        <?php } ?>
          </table>
    </body>
</html>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

前提

$new_img_filenameはアップロードして配置した先のファイルパスですよね。
文字列のはずです。

設定されているのは下記のようですね。

$new_img_filename = sha1(uniqid(mt_rand(), true)). '.' . $extension;


そもそも文字列なのでforeachには入れられません。

$test = 'aaa/bbb.jpg';
foreach($test as $v){
    echo $v.PHP_EOL;
}

//PHP Warning:  Invalid argument supplied for foreach()

学習期には必ずPHPのエラー表示はONにしましょう。

本題

登録したデータを取得しているのは下記ですね。

    $sql ='select drink_name,price,img,create_datetime from test_drink_master';
    $stmt = $dbh->prepare($sql);
    $stmt->execute(null);
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $data .= "<p>".$row['create_datetime']." ".$row['drink_name']." ".$row['price']." ".$row['img']."</p>";
    }

$dataという変数に追記で文字列を追加していっているだけです。

HTML上はimgタグを利用することで画像ファイルパスの画像を読み込みに行きます。単なる文字列で書いても何もとりにいきません。

確認すべきは「画面に表示された状態」ではなく「HTMLソースが想定通り出力できているか」です。
ブラウザに右クリックで「ページのソースを表示」という機能があると思うのでそちらで出力結果を確認してください。

PHP側はURLやフォーム送信などのリクエストを受け取って処理し、情報を出力しているだけで、どこから参照されるかというのは知りません。
ブラウザから参照される前提なのであれば必ずブラウザ見る、HTML構文にそった状態で埋め込んであげる必要があります。

    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $data .= "<p>".$row['create_datetime']." ".$row['drink_name']." ".$row['price']." <img src='".$row['img']."' /></p>";
    }

※もちろんURLから参照できるパスでないとimgタグに入れ込んでも画像表示できませんので、そこはデータとファイルアップロード先をご確認ください。

若干蛇足

あと、まだ学習元では学んでないのかもしれませんが、画面出力時にHTMLエスケープは必須です。
XSSなどで調べて概念を理解し、適切に対応していくようにしてください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/21 23:05

    丁寧なご回答ありがとうございます。
    いただいたアドバイスをもとに取り組んでみます。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る