PHP入門 データベース パラメーター値のバインド

パラメーターのデータ型を宣言する(バイナリデータの操作)

bindValueメソッドでは、パラメーターのデータ型を指定することができます。たとえばバイナリ型のパラメータを扱うようなケースでは、データ型を明示的に宣言する必要があります。

例:photoテーブルに対してブラウザからアップロードされた画像を登録

photoテーブル

フィールド名データ型概要
idINT写真ID(主キー/自動連番)
typeVARCHAR(50)ファイルの種類
dataMEDIUMBLOB写真データ

sample1.php

<IDOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>画像のアップロード</title>
</head> 
<body>
<form method="POST" enctype="multipart/form-data" action="bindValue_process.php">
<input id="photo" type="file" name="photo" size="50" /> 
<input type="submit" value="アップロード" />
</form>
</body> 
</html>

bindValue_process.php

<?php
require_once './DbManager.php';

try {
    // データベースへの接続を確立
    $db = getDb();
    // INSERT命令在準備
    $stt = $db->prepare('INSERT INTO photo (type, data) VALUES (:type,:data)');
    // プレイスホルダーにアップロードファイルの情報をセット
    $file = fopen($_FILES['photo']['tmp_name'], 'rb'); //➋
    $stt->bindValue(':type', $_FILES['photo']['type'], PDO:: PARAM_STR); 
    $stt->bindValue(':data', $file, PDO:: PARAM_LOB);  //➊
    // INSERT命令実行 
    $stt->execute();
    print '写真のアップロードに成功しました。';
} catch(PDOException $e) {
    die("エラーメッセージ:{$e->getMessage()}");
}
実行結果
初期画面:画像ファイルを選択した後
実行結果
アップロード画面後の画面

バイナリデータを扱う場合には、PDO::PARAM_LOB(ラージオブジェクト型)であることを明示します(❶)。データ型の指定がない場合は、正しくバイナリデータは処理されません。バイナリデータはファイルハンドルとして渡します。アップロードファイルはスーパーグローバル変数$_FILESのtemp_nameキーで取得できるので、これをfopen関数でオープンします(❷)。一時ファイルは、move_uploaded_file関数で処理されなかった場合、スクリプトの処理後に自動的に破棄されます。

サイズの大きなファイル

サイズの大きなファイルは、PHPまたはMariaDBの制限でアップロードできない場合があります。その場合は、MariaDBの設定ファイル「my.ini/my.cnf」の「max_allowed_packet」パラメーターを確認します。「max_allowed_packet」パラメーターはクライアントからサーバーに送信できる最大のパケットサイズを大きくすることで問題が解消されます。

[mysqld]
max_allowed_packet=3M

bindValueメソッドとbindParamメソッド

bindValueメソッドによく似たメソッドとして、bindParamメソッドがあります。bindValueメソッドが値を直接バインドするのに対して、bindParamメソッドは指定された変数の参照をバインドします。つまりは、bindParamメソッドによってバインドされた変数の内容は、executeメソッドが呼び出されたタイミングで評価されるということです。

例:

sample1.php


<?php
require_once './DbManager.php';
require_once './Encode.php';
try {
// データベースへの接続を確立
$db = getDb();
// すべての書籍情報を刊行日について降順に取得
$stt = $db->query('SELECT * FROM book ORDER BY published DESC'); // フォーム要素に付与するための連番を表す変数$cntを定義
$cnt = 0;
?>

<IDOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>サンプル</title>
</head>

<body>
<form method="POST" action="bindParam_process.php">
<input type="submit" value="更新" />
<table class="table">
<thead>
<tr>
    <th>ISBNコード</th>
    <th>書名</th>
    <th>価格</th>
    <th>出版社</th>
    <th>刊行日</th>
</tr>
</thead>
<tbody>
<?php
//取得した書籍情報を基に一覧表フォームを作成
while ($row = $stt->fetch (PDO:: FETCH_ASSOC)) { $cnt++;
?>
<tr> 
    <td>
        <?=e($row['isbn']) ?>
        <input type="hidden" name="isbn<?=e($cnt) ?>" value="<?=e($row['isbn']) ?>" />
    </td>
    <td>
        <input type="text" name="title<?=e($cnt) ?>" value="<?=e($row['title']) ?>" size="45" />
    </td>
    <td>
        <input type="text" name="price<?=e($cnt) ?>" value="<?=e($row['price']) ?>" size="5" />
    </td>
    <td>
        <input type="text" name="publish<?=e($cnt) ?>" value="<?=e($row['publish']) ?>" size="12" />
    </td>
    <td>
        <input type="text" name="published<?=e($cnt) ?>" value="<?=e($row['published']) ?>" size="12" />
    </td>
</tr>
<?php
}
} catch (PDOException $e) {
    die("エラーメッセージ: {$e->getMessage()}");
}
?>
</tbody>
<input type="hidden" name="cnt" value="<?=e($cnt) ?>">
</form>
</body>
</html>

bindParam_process.php


<?php
require_once './DbManager.php'; 
try {
    // データベースへの接続を取得
    $db = getDb();
    // bookテーブルを更新するためのUPDATE命令を準備
    $stt = $db->prepare('UPDATE book SET title=:title, price=:price, publish=:publish, published=:published WHERE isbn=:isbn');
    // プレイスホルダーにバインドする変数を関連付け 
    $stt->bindParam(':isbn', $isbn); 
    $stt->bindParam(':title', $title); 
    $stt->bindParam(':price', $price);
    $stt->bindParam(':publish', $publish);
    $stt->bindParam(':published', $published);
    // フォームからの入力値を順に取得し、対応する変数にセット
    // (要素名はisbn1 2... titlel 2............... のように連番が振られているはず) 
    for ($i= 1; $i <= $_POST['cnt']; $i++) {
        $isbn = $_POST['isbn'.$i];
        $title = $_POST['title'.$i];
        $price = $_POST['price'.$i]; 
        $publish = $_POST['publish'.$i];
        $published = $_POST['published'.$i]; // UPDATE命令を実行
        $stt->execute();
    }
    // 処理後は元のフォームにリダイレクト
    header('Location: http://'.$_SERVER['HTTP_HOST']. '/sample1.php');
} catch (PDOException $e) {
    die("エラーメッセージ: {$e->getMessage()}");
}

実行結果
実行結果

変数の値を変化させながら、繰り返しSQL命令を実行していくようなケースでは、bindParamメソッドを利用します。

構文:fetchObjectメソッド

PDOStatement::bindParam(mixed $parameter, mixed &$variable 
                 [, int $data_type = PDO::PARAM_STR[, int $length]]): bool
$parameterパラメーター名(またはインデックス番号)
&$variableバインドする変数
$data_typeデータ型
$lengthデータ長

なお、bindParamメソッドには、リテラルを直接指定することはできません。