はじめに
PHPを勉強しはじめたばかりの素人メモです。
お目汚しすいません。
助言を頂けますと、とてもうれしいです。
よろしくお願いします。
コード
同一ページ内で、
入力→確認(画像プレビューあり)→PDOでデータベースに登録(mysql)をします。
<?php
session_start();
$name = '';
$pass = '';
$errors = array();
// エラー確認
if(!empty($_POST)) {
if (!isset($_POST['name']) || $_POST['name'] === '') {
$errors['name'] = 'ニックネームが入力されていません';
} else {
$name = htmlspecialchars($_POST['name'], ENT_QUOTES);
}
if (!isset($_POST['password']) || $_POST['password'] === '') {
$errors['password'] = 'パスワードが入力されていません';
} else {
if (strlen($_POST['password']) < 4){
$errors['passwordlength'] = 'パスワードは4文字以上で入力してください。';
} else {
$password = htmlspecialchars($_POST['password'], ENT_QUOTES);
}
}
if (!isset($_POST['password2']) || $_POST['password2'] === '') {
$errors['password2'] = '確認用パスワードを入力してください。';
} else {
$password2 = htmlspecialchars($_POST['password2'], ENT_QUOTES);
if ($password != $password2){
$errors['password12'] = 'パスワードが一致していません。';
} else {
// パスワード
$options = [
'cost' => 9,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$pass = password_hash("$password", PASSWORD_BCRYPT, $options)."\n";
}
}
}
// 画像をリサイズして保存
if (isset($_FILES['upfile']['error']) && is_int($_FILES['upfile']['error'])) {
try {
// $_FILES['upfile']['error'] の値を確認
switch ($_FILES['upfile']['error']) {
case UPLOAD_ERR_OK: // OK
break;
case UPLOAD_ERR_NO_FILE: // ファイル未選択
throw new RuntimeException('ファイルが選択されていません');
case UPLOAD_ERR_INI_SIZE: // php.ini定義の最大サイズ超過
case UPLOAD_ERR_FORM_SIZE: // フォーム定義の最大サイズ超過
throw new RuntimeException('ファイルサイズが大きすぎます');
default:
throw new RuntimeException('その他のエラーが発生しました');
}
$info = @getimagesize($_FILES['upfile']['tmp_name']);
if (!$info = @getimagesize($_FILES['upfile']['tmp_name'])) {
throw new RuntimeException("[{$k}] 有効な画像ファイルを指定してください");
}
if (!in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG], true)) {
throw new RuntimeException("未対応の画像形式です");
}
// 画像処理に使う関数名
$create = str_replace('/', 'createfrom', $info['mime']);
$output = str_replace('/', '', $info['mime']);
// 縦横比を維持、120 * 120 以下に収まるサイズを求める
if ($info[0] >= $info[1]) {
$dst_w = 120;
$dst_h = ceil(120 * $info[1] / max($info[0], 1));
} else {
$dst_w = ceil(120 * $info[0] / max($info[1], 1));
$dst_h = 120;
}
// リサンプリング先画像リソースを生成
$dst = imagecreatetruecolor($dst_w, $dst_h);
// 元画像リソースを生成
if (!$src = @$create($_FILES['upfile']['tmp_name'])) {
throw new RuntimeException("画像リソースの生成に失敗しました");
}
// getimagesize関数で得られた情報も利用してリサンプリング
imagecopyresampled($dst, $src, 0, 0, 0, 0, $dst_w, $dst_h, $info[0], $info[1]);
ob_start();
$output ($dst);
$content = base64_encode(ob_get_contents());
ob_end_clean();
imagedestroy($dst);
$_SESSION['content'] = $content;
$msg = ['green', 'ファイルは正常に読み込まれています。'];
} catch (RuntimeException $e) {
$msg = ['red', $e->getMessage()];
}
}
// リライトするときの設定
if(isset($_GET['action']) && $_GET['action'] === 'edit'){
$name = $_SESSION['name'];
}
// エラーがなかったら、
if(count($errors) === 0){
$_SESSION['name'] = $name;
$_SESSION['password'] = $pass;
}
// 登録ボタンが押されたらインサート処理開始
if(!empty($_POST['register'])){
require_once 'dbmanager.php';
try{
$pdo = getDb();
$sql = 'INSERT INTO members(name,password,picture) VALUES(:name, :password, :picture)';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':name', $_SESSION['name'], PDO::PARAM_STR);
$stmt->bindParam(':password', $_SESSION['password'], PDO::PARAM_STR);
$stmt->bindParam(':picture', $_SESSION['content'], PDO::PARAM_STR);
$stmt->execute();
header('Location: thanks.php');
} catch (PDOException $e) {
echo $e->getMessage();
}
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>登録画面</title>
</head>
<body>
<?php
// エラーメッセージ表示
echo "<ul>";
foreach($errors as $value){
echo"<li>";
echo $value;
echo"</li>";
}
echo "</ul>";
?>
<?php if (!isset($_POST['submit']) || $_POST['submit'] === '') : ?>
<form enctype="multipart/form-data" method="post" action="">
<dl>
<dt>ニックネーム<span class="required">必須</span></dt>
<dd><input type="text" name="name" size="35" maxlength="255" value="<?php if(isset($name)){ echo $name; } ?>">
</dd>
<dt>ログインパスワード<span class="required">必須</span></dt>
<dd><input type="password" name="password" size="10" maxlength="20" value=""></dd>
<dt>確認用パスワード<span class="required">必須</span></dt>
<dd><input type="password" name="password2" size="10" maxlength="20" value=""></dd>
<dt>プロフィール画像など(GIF, JPEG, PNGのみ対応)</dt>
<dd><input type="file" name="upfile" /></dd>
<p><input type="submit" value="submit" name="submit"/></p>
</dl>
</form>
<?php elseif( count($errors) > 0) : ?>
<form enctype="multipart/form-data" method="post" action="">
<dl>
<dt>ニックネーム<span class="required">必須</span></dt>
<dd><input type="text" name="name" size="35" maxlength="255" value="<?php if(isset($name)){ echo $name; } ?>">
</dd>
<dt>ログインパスワード<span class="required">必須</span></dt>
<dd><input type="password" name="password" size="10" maxlength="20" value=""></dd>
<dt>確認用パスワード<span class="required">必須</span></dt>
<dd><input type="password" name="password2" size="10" maxlength="20" value=""></dd>
<dt>プロフィール画像など(GIF, JPEG, PNGのみ対応)</dt>
<dd><input type="file" name="upfile" /></dd>
<p><input type="submit" value="submit" name="submit"/></p>
</dl>
</form>
<?php else: ?>
<form action="" method="post" enctype="multipart/form-data">
<dl>
<dt>ニックネーム<span class="required">必須</span></dt>
<dd><?php if(isset($name)){ echo $name; } ?></dd>
<dt>ログインパスワード<span class="required">必須</span></dt>
<dd>【表示されません】</dd>
<dt>プロフィール画像など</dt>
<dd>
<?php if (isset($info)): ?>
<img src="data:<?php echo$info[mime] ?>;base64,<?php echo $content;?>" alt="sample" /><br>
<?php endif; ?>
<?php if (isset($msg)): ?>
<span style="color:<?=$msg[0]?>;"><?=$msg[1]?></span>
<?php endif; ?>
</dd></dl>
<div><a href="?action=edit">« 書き直す</a>|<input type="submit" name="register" value="登録する" /></div>
</form>
<?php endif; ?>
</body>
</html>
こんな感じ
参考サイト
『file_get_contens(URL)で取得した画像をPHPで表示したい』 http://q.hatena.ne.jp/1313160119
『file_get_contentsで画像やFlashを表示とか』 http://d.hatena.ne.jp/m0r1/20090412/1239512576
『PHPについての質問です。フォームの確認画面で入力した画像をプレビュー表示させるにはどのようにすればいいですか?』 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12141865207
『画像アップロード処理サンプル集』 http://qiita.com/mpyw/items/73ee77a9535cc65eff1e
『PHP+MySQLで簡易画像アップローダ』 http://qiita.com/mpyw/items/117ab6a88fd58d911c34
『【PHP】mysqlに画像を保存する』 http://startnews24.com/?p=15970
『[PHP]GDで作った画像をファイル化せずに直接タグで表示する』 http://php-archive.net/php/data-uri-scheme/
最後まで理解できなかったこと……
リサイズした画像データをどう取り出せばよいのか、理解できていません。
一応、データベースに格納できたし、出力もできましたが、もっとスマートな方法があるはず……絶対この方法はおかしい。
<?php
require_once 'dbmanager.php';
$pdo = getDb();
$sql = "select picture from members where id = 36";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$img = $row['picture'];
?>
<img src="data:image/jpeg;base64,<?php echo $img;?>" alt="sample" /><br>
このように画像を表示しましたが……。
感動したこと
(言われてみれば当たり前なことだけれど)画像データが文字列で取り出せるってことにものすっごく感動しました。
最後に
どこに問題があるのか分からないど素人が書きました。
いるとは思いませんが、念のため。絶対にこのまま使用しないでください。
理解力が全然足りておらず、セキュリティ的に問題がたくさんあると思われますので。
こうすれば良いや、これはセキュリティ的にヤバい、などご助言いただけるととてもとても嬉しいです。よろしくお願いします。
(写真はhttps://unsplash.com/さまからお借りしました。)