前回OmniGraffleでワイヤーフレームをつくったので、しばらく(簡易)画像掲示板というか画像アップローダもどきを作ろうと思う(データベースを利用しない簡易アップローダは以前やった)。ドットインストールで画像掲示板をつくるレッスンがあり、他のも参考にさせてもらいながら作ろうかなと。今回は指定した画像をサーバーに格納するのと、フォームの値をMySQLデータベースに登録するところまで。
成果物:upload.html
やったことメモ
- HTMLでフォームをつくった
- 選択ボタン設置するときはinputタグのtypeを”file”にする
- 選択はselectタグ
- MySQLデータベースとテーブルをつくった
- データベースとテーブルの作成はphpMyAdminを使った
- テーブルのカラムは、ID(自動付与)、名前、投稿時間(自動付与)、ファイル名、OS(iOS/Android)、更新・削除キー、コメント、アクセス数の8つ
- 画像をimagesディレクトリに格納してサムネイルをつくってthumbnailsディレクトリに格納した
- フォームの値は、PHPの$_FILESで参照できる。
- filesize
- getimagesize
- move_uploaded_file
- imagecreatefromgif/imagecreatefromjpeg/imagecreatefrompng
- imagecreatetruecolor
- imagecopyresampled
- imagegif/imagejpeg/imagepng
- HTMLフォームの値をPHPのPDO(PHP Data Objects)でデータベースに挿入した
- PDOのコンストラクタの第1引数はデータソース名(data source name/dsn)。ホストはサーバーの管理パネルにある。
- データベースの接続=PDOインスタンスの生成(データベースハンドラ)/切断=データベースハンドラにnull代入
- プリペアドステートメントでデータベースに挿入した
- IDや投稿時間などオートインクリメントや処理実施時刻を設定したものはinsert文に書かなくても値挿入される
- データベースに値が挿入されていること、画像がフォルダにアップロードされていることを確認した
ソースコード
upload.html
<html lang="ja"> <head> <meta charset="UTF-8"> <title>スマホキャプチャーギャラリー</title> </head> <body> <a href="index.html">Home</a> | <a href="upload.html">アップロード</a> | <a href="ranking.html">人気順</a> | <a href="latest.html">新着順</a> <p>アップロード画面[upload.html]:フォーム(プレビュー欲しい)、エラーチェック(必須項目、ファイル形式、ファイルサイズ、コメント上限)</p> <form action="upload.php" method="post" enctype="multipart/form-data"> <p> <label for="">画像:<input type="file" name="image" /></label> </p> <p> <label for="">名前:<input type="text" name="name" size="40" /></label> </p> <p> <label for="">OS:<select name="os"> <option value="default">選択してください</option> <option value="iPhone">iPhone</option> <option value="Android">Android</option> </select> </label> </p> <p> <label for="">コメント:<br /><textarea id="" name="comment" rows="10" cols="30"></textarea></label> </p> <p> <label for="">編集・削除キー:<textarea id="" name="updelkey" rows="1" cols="30"></textarea></label> </p> <p> <input type="submit" value="送信" /> </p> </form> </body>
upload.php
<?php require_once('config.php'); if ($_FILES['image']['error'] != UPLOAD_ERR_OK) { echo 'error occured:'.$_FILES['image']['error']; exit; } $size = filesize($_FILES['image']['tmp_name']); if (!$size || $size > MAX_FILE_SIZE) { echo 'filesize invalid: 0 or too big'; exit; } // *** 画像の格納 *** $imagesize = getimagesize($_FILES['image']['tmp_name']); switch ($imagesize['mime']) { case 'image/gif': $ext = '.gif'; break; case 'image/jpeg': $ext = '.jpg'; break; case 'image/png': $ext = '.png'; break; default: echo 'gif/jpeg/png only'; exit; } $imageFileName = sha1(time().mt_rand()) . $ext; $imageFilePath = IMAGES_DIR . '/' . $imageFileName; $rs = move_uploaded_file($_FILES['image']['tmp_name'], $imageFilePath); if (!$rs) { echo "could not upload"; exit; } // *** サムネイルの生成と格納 *** $width = $imagesize[0]; $height = $imagesize[1]; if ($width > THUMBNAIL_WIDTH) { switch ($imagesize['mime']) { case 'image/gif': $srcImage = imagecreatefromgif($imageFilePath); break; case 'image/jpeg': $srcImage = imagecreatefromjpeg($imageFilePath); break; case 'image/png': $srcImage = imagecreatefrompng($imageFilePath); break; } $thumbHeight = round($height * THUMBNAIL_WIDTH / $width); $thumbImage = imagecreatetruecolor(THUMBNAIL_WIDTH, $thumbHeight); imagecopyresampled($thumbImage, $srcImage, 0, 0, // コピー先の始点(dst_x, dst_y) 0, 0, // コピー元の始点(src_x, src_y) THUMBNAIL_WIDTH, $thumbHeight, // コピー先の幅と高さ $width, $height); // コピー元の幅と高さ switch ($imagesize['mime']) { case 'image/gif': imagegif($thumbImage, THUMBNAIL_DIR.'/'.$imageFileName); break; case 'image/jpeg': imagejpeg($thumbImage, THUMBNAIL_DIR.'/'.$imageFileName); break; case 'image/png': imagepng($thumbImage, THUMBNAIL_DIR.'/'.$imageFileName); break; } } // *** フォームの情報をデータベースに格納 *** try { $dbh = new PDO(DSN, DB_USER, DB_PASS); } catch (PDOException $e) { var_dump($e->getMessage()); exit; } $statement = $dbh->prepare("insert into mobile_capture_showcase (name,filename,os,updelkey,comment,counter) values (:name,:filename,:os,:updelkey,:comment,0)"); $statement->bindParam(":name", $_POST['name']); $statement->bindParam(":filename", $imageFileName); $statement->bindParam(":os", $_POST['os']); $statement->bindParam(":updelkey", $_POST['updelkey']); $statement->bindParam(":comment", $_POST['comment']); $statement->execute(); $dbh = null; // *** ホームに戻る *** header('Location: http://' . $_SERVER['SERVER_NAME'] . '/study/uploader/mobile_capture_showcase/index.html'); exit; ?>
config.php
<?php define('DSN', 'mysql:host=xxxxx;dbname=xxxxx;'); define('DB_USER', 'xxxxxxxxxxx'); define('DB_PASS', 'xxxxxxxxxxx'); define('IMAGES_DIR', dirname($_SERVER['SCRIPT_FILENAME']).'/images'); define('THUMBNAIL_DIR', dirname($_SERVER['SCRIPT_FILENAME']).'/thumbnails'); define('THUMBNAIL_WIDTH', 160); define('MAX_FILE_SIZE', 819200); // 800KB(800*1024) error_reporting(E_ALL & ~E_NOTICE); if (!function_exists('imagecreatetruecolor')) { echo "GDがインストールされていません"; exit; } ?>
次回以降にやろうと思っていること
- エラーチェックをする(必須項目、ファイル形式、ファイルサイズ、コメント上限)
- トップページに画像一覧を表示する
- トップページの画像クリックで個別ページに遷移させる
- 投稿時間の降順で新着順ページを表示する(表示方法はトップページのを流用できるはず)
- 個別ページヘのアクセスをカウントする
- アクセス数の降順で人気順ページを表示する(表示方法は新着順ページのを流用できるはず)
- 個別ページに編集リンクを用意&データ編集できるようにする
- 個別ページに削除リンクを用意&データ削除できるようにする
- CSSフレームワーク(Twitter Bootstrap)を適用する
以上でベースができるはずで、さらに追加したいこと
- アップロードフォームに画像プレビューを設置する
- ページング機能を新着順、人気順ページに設置する
- トップページと個別ページにソーシャルボタンを設置する
- OSごとに新着順・人気順ページを表示する
参考サイト
- HTML5リファレンス
- PHPの基礎(応用編) (全12回) – ドットインストール
- PHP: PDO – Manual
- PHPで作る「画像掲示板」 (全18回) – ドットインストール
- お問合せ管理システムを作ろう (全21回) – ドットインストール
- PHP/jQueryで作るToDoアプリ (全20回) – ドットインストール
- PHPで作る「ページング機能」 (全10回) – ドットインストール
パーフェクトPHP (PERFECT SERIES 3)
posted with amazlet at 13.01.30
小川 雄大 柄沢 聡太郎 橋口 誠
技術評論社
売り上げランキング: 24,082
技術評論社
売り上げランキング: 24,082
関連エントリー