LoginSignup
16
14

More than 5 years have passed since last update.

【PHP】入力→確認→PDOで登録。を同一ページで

Last updated at Posted at 2015-09-07

はじめに

PHPを勉強しはじめたばかりの素人メモです。
お目汚しすいません。
助言を頂けますと、とてもうれしいです。
よろしくお願いします。

コード

同一ページ内で、
入力→確認(画像プレビューあり)→PDOでデータベースに登録(mysql)をします。

sample.php
<?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">&laquo;&nbsp;書き直す</a>|<input type="submit" name="register" value="登録する" /></div>
</form>
<?php endif; ?>

</body>
</html>

こんな感じ

入力画面
form1.png
エラー
form2.png
確認画面
form3.png

参考サイト

『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/

最後まで理解できなかったこと……

リサイズした画像データをどう取り出せばよいのか、理解できていません。
一応、データベースに格納できたし、出力もできましたが、もっとスマートな方法があるはず……絶対この方法はおかしい。

view.php
<?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/さまからお借りしました。)

16
14
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14