• ベストアンサー

PDO学び始めました

プログラム初心者です PDO学び始めたのですがわからないとこがあります 質問1 名前付きプレースホルダの:nameの前についているコロンはなんですか? 変数なんでしょうか? 質問2 bindValueとbindParamがあるようですが普通につかう範囲では数値も文字もbindValueを使うだけでいいですか? 質問3 ユーザー入力のない値の場合はbindValueを使わずにprepareとexecuteのみでいいですか? 質問4 下記のように$nameの変数が後から登場しているのにエラーにならないのはなんでなんですか? $stmt = $pdo -> prepare("INSERT INTO テーブル名 (name, value) VALUES (:name, :value)"); $stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindValue(':value', $value, PDO::PARAM_INT); $name = 'one'; $value = 1; $stmt->execute(); よろしくお願いします

  • flash0
  • お礼率97% (297/306)
  • PHP
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
noname#244856
noname#244856
回答No.1

以前にも何回も掲載しましたが一応もう一度貼っておきます。何回か更新した内容があるので良ければもう一度軽く目を通してみてください。 Qiita - PHPでデータベースに接続するときのまとめ http://qiita.com/mpyw/items/b00b72c5c95aac573b71 【回答1】 変数のようなイメージで構いませんが、変数と決定的に違うのは、値を "後から" 割り当てることですね。 ・変数を埋め込んだ場合 →prepareのタイミングで値が割り当てられる ・プレースホルダを使い、prepare・bindValue・executeで実行した場合 →bindValueのタイミングで値が割り当てられる ・プレースホルダを使い、prepare・bindParam・executeで実行した場合 →executeのタイミングで値が割り当てられる(bindParamでは参照状態にするだけ) 【回答2】 疑問符プレースホルダの例で解説しますが、基本的には $stmt = $pdo->prepare('SELECT * FROM people WHERE name = ? AND age = ?'); $stmt->bindValue(1, $name, PDO::PARAM_STR); // PDO::PARAM_STRは省略可能 $stmt->bindValue(2, $age, PDO::PARAM_INT); $stmt->execute(); で構いません。但し、もしバインド内容がすべて文字列である場合は $stmt = $pdo->prepare('SELECT * FROM people WHERE name = ? AND age = ?'); $stmt->bindValue(1, $name); $stmt->bindValue(2, $age); $stmt->execute(); とする代わりに $stmt = $pdo->prepare('SELECT * FROM people WHERE name = ? AND age = ?'); $stmt->execute(array($name, $age)); のようにスッキリ書くことが出来ます。名前付きプレースホルダの場合は $stmt = $pdo->prepare('SELECT * FROM people WHERE name = ? AND age = ?'); $stmt->execute(compact('name', 'age')); でどうぞ。このあたりの説明もQiitaの記事と全部重複しているので、そちらを読んでもらえれば全部疑問も解決すると思いますが。「エミュレーション」にも注意してください。 【回答3】 ・結果をPDOStatementとして取得する場合 → $pdo->query() ・作用した行数だけが分かれば十分、もしくはそれすらも不要な場合 → $pdo->exec() 【回答4】 回答1に書いたことがこっちの答えになってると思います。bindParamは変数を参照状態にして割り当てるだけで、値の読み取りはexecuteするまで行われません。更にいうならば、参照状態にした時点で未定義の変数はNULLとしてエラーを出さずに初期化されるので、たとえ値の設定を行わなわなかったとしてもエラーが発生するわけではありません。 [Notice: undefined variable が発生する] function test($var) {  var_dump($var); } test($hogehoge); [Notice: undefined variable が発生しない] function test(&$var) {  var_dump($var); } test($hogehoge);

flash0
質問者

お礼

丁寧な回答ありがとうございます とてもわかりやすかったです コードもmysqliより短くできるので積極的に使っていきたいと思います

その他の回答 (1)

noname#244856
noname#244856
回答No.2

訂正 $stmt = $pdo->prepare('SELECT * FROM people WHERE name = :name AND age = :age'); $stmt->execute(compact('name', 'age'));

flash0
質問者

お礼

ありがとうございました

関連するQ&A

  • PDOについて

    プログラム初心者です 最近PDO使うようになりましたがまったく使いこなせません 何回もSQL発行して効率わるいコードになりました(--; 一回のSQL発行にまとめる方法はありますか? for ($i=0; $i<$count; $i++) { $id=$Array[$i][0]; $name=$Array[$i][1]; $stmt = $pdo -> prepare("INSERT IGNORE INTO table(id,name) VALUES (?,?)"); $stmt->bindValue(1, $id, PDO::PARAM_INT); $stmt->bindValue(2, $name, PDO::PARAM_STR); $stmt->execute(); } 質問2 prepareのキャッシュを利かすってどうゆうことでしょうか?上の場合でもキャッシュ生かせていますか? よろしくお願いします

    • ベストアンサー
    • PHP
  • PDOで取得すると全てSTRING型で取得する?

    PDOを利用してprepareとbindValueでPDO::PARAM_INTなどと型指定をしてINSERTしているのですが、ネットをいろいろ見てみると「型指定をしてもexecute()時に全ての型は文字列として扱われる」と書いています。 これはデータベースの各カラムの型は無視して全て文字列としてINSERTしているのでしょうか? それともデータベースの型にMySQL側で勝手に変換して値を挿入してくれるのでしょうか? INSERTした数値を含むデータをprepareでSELECTしてexecute()してみると数値を含めて全てのカラムがstringとして取得しています。 MySQL側ではカラムの型をINTやFROATとして定義しても数値を文字列として挿入するとMySQL側も文字列として扱うのですか?それとも数値に変換されて挿入されますか? もし文字列として挿入されたらインデックスに影響しますか? いまいちどうすればいいのかわかりません。 一応 $id = 1; $name = "hoge"; $float = 0.055; $stmt = $dbh->prepare("INSERT INTO REGISTRY (id, name, float) VALUES (:id, :name, :float)"); $stmt->bindValue(:id, $id, PDO::PARAM_INT); $stmt->bindValue(:name, $name, PDO::PARAM_STR); $stmt->bindValue(:float, (string)$float, PDO::PARAM_STR); としています。 あと、PDO::PARAM_FLOATはないみたいで、PDO::PARAM_STRにすべきと書いていますが、このように指定してもMySQL側で勝手にFLOAT型に変換して値をINSERTするのでしょうか? どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL
  • PDOのprepareでLIKEの部分一致が使えません・・

    http://d.hatena.ne.jp/Sybian/20070521/p1 のサイトの例のように、LIKE '%文字列%' をprepareしようとしたのですが上手く結果が返りません。 PDOのプリペアステートメントは、 LIKEの部分一致や先頭一致に非対応なのでしょうか? $query="SELECT * FROM table WHERE id=:id OR like name='%:name%'"; $pdo=new PDO('mysql:host=localhost;dbname=database','user','password'); $stmt=$pdo->prepare($query); $stmt->bindValue(':id',$id,PDO::PARAM_INT); $stmt->bindValue(':name',$name,PDO::PARAM_STR); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC);

    • ベストアンサー
    • PHP
  • PHP pdo データが無い場合とある場合

    tablename( id int not null, name text not null, age int ); 的なテーブルがあったとして、id番号と名前は必ずデータがあるが、年齢はデータがあったり無かったりするとします。 $id = 1; $name = "太郎"; $age = ""; だったり $age = "25";だったり シンプルにinsert 書きたいのですが、やはり$ageが空文字の場合と数字で構成される文字の場合でわけないと書けないでしょうか? $sql = "insert into tablename( id,name,age) values (:id,:name,:age); $stmt = $pdo->prepare($sql); $stmt->bindValue(":id", $id, PDO::PARAM_INT); $stmt->bindValue(":name", null, PDO::PARAM_STR); if ($age === "") { $stmt->bindValue(":age ", null, PDO::PARAM_NULL); } else { $stmt->bindValue(":age ", $age , PDO::PARAM_INT); } とわけないと無理?

    • 締切済み
    • PHP
  • pdoでバインドしない場合のデメリット

    $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'); $sth->bindParam(':calories', $calories, PDO::PARAM_INT); $sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12); $sth->execute(); 上記ではなく $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?'); $sth->execute(array($calories,$colour)); のようにbindParamやbindValueを使わない場合は危険はあるのでしょうか? ご教示頂けますと幸いです。 宜しくお願いいたします。

    • ベストアンサー
    • MySQL
  • ステートメントが必要です。???

    いつも大変お世話になり誠にありがとうございます。 標記の件。 下記のコードの一番下の}にステートメントが必要です と出ます。 どういう意味でしょうか? どうか教えてください。 宜しくお願い申し上げます。      記 function blogUpdate($blogs) { $sql = "UPDATE $this->table_name SET title = :title, content = :content, category = :category, publish_status = :publish_status Where id = :id"; $dbh = $this->dbConnect(); $dbh->biginTransaction(); try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':title', $blogs['title'], PDO::PARAM_STR); $stmt->bindValue(':content', $blogs['content'], PDO::PARAM_STR); $stmt->bindValue(':category', $blogs['category'], PDO::PARAM_INT); $stmt->bindValue(':publish_status', $blogs['publish_status'], PDO::PARAM_INT); $stmt->bindValue(':id', $blogs['id'], PDO::PARAM_INT); $stmt->execute(); $stmt->commit(); echo 'ブログを更新しました!'; } catch (PDOException $e) { $dbh->rollBack(); exit($e); } }

    • ベストアンサー
    • PHP
  • $dbh = dbConnect();

    いつもお世話になりありがとうございます。 標記の件。 エラーになります。 どう直せばいいでしょうか? エラーメッセージは Fatal error: Uncaught Error: Call to undefined function dbConnect() in C:\xampp\htdocs\blog_create.php:9 Stack trace: #0 {main} thrown in C:\xampp\htdocs\blog_create.php on line 9 です。 コーディングは下記です。 <?php //require_once('form.html'); require_once('blog.php'); $sql = "INSERT INTO table_name(name,title,category,content) VALUES (:name, :title, :category, :content,)"; $dbh = dbConnect(); $dbh->beginTransaction(); try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', $blogs['id'], PDO::PARAM_INT); $stmt->bindValue(':name', $blogs['name'], PDO::PARAM_STR); $stmt->bindValue(':title', $blogs['title'], PDO::PARAM_STR); $stmt->bindValue(':category', $blogs['category'], PDO::PARAM_STR); $stmt->bindValue(':content', $blogs['content'], PDO::PARAM_STR); $stmt->bindValue(':post_at', $blogs['post_at'], PDO::PARAM_INT); $stmt->execute(); $stmt->commit(); echo 'ブログを投稿しました!'; } catch (PDOException $e) { $dbh->rollBack(); exit($e); } blog.php <?php //require_once('dbc.php'); //<?php //class Dbc //{ // protected $table_name; //protected function dbConnect() //{ $dsn = 'mysql:host=localhost;dbname=blog_app;charset=utf8'; $user = 'blog_user'; $pass = 'rhythm0!KT'; try { $dbh = new \PDO($dsn, $user, $pass, [ \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, ]); } catch (PDOException $e) { echo '接続失敗' . $e->getMessage(); exit(); }; return $dbh; //} function getAll() { $dbh = $this->dbConnect(); //①SQLの準備 $sql = "SELECT * FROM $this->table_name"; //②SQLの実行 $stmt = $dbh->query($sql); //③SQLの結果を受け取る $result = $stmt->fetchall(\PDO::FETCH_ASSOC); return $result; $dbh = null; } $dbh = $this->dbConnect(); $sql = "SELECT * FROM $this->table_name"; $stmt = $dbh->prepare("SELECT * FROM $this->table_name Where id = :id"); $stmt->bindValue(':id', (int)$id, \PDO::PARAM_INT); $stmt->execute(); $result = $stmt->fetch(\PDO::FETCH_ASSOC); if (!$result) { exit('本文がありません。'); } return $result; //} //function blogCreate($blogs) { $sql = 'INSERT INTO blog(title, content, category, publish_status) VALUES (:title, :content, :category, :publish_status)'; $dbh = $this->dbConnect(); $dbh->biginTransaction; try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':title', $blogs['title'], \PDO::PARAM_STR); $stmt->bindValue(':content', $blogs['content'], \PDO::PARAM_STR); $stmt->bindValue(':category', $blogs['category'], \PDO::PARAM_INT); $stmt->bindValue(':publish_status', $blogs['publish_status'], \PDO::PARAM_INT); $stmt->execute(); $dbh->commit(); echo 'ブログを投稿しました!'; } catch (PDOException $e) { $dbh->rollBack(); exit($e); } } function delete($id) { if (empty($id)) { exit('idが不正です。'); } $dbh = $this->dbConnect(); $stmt = $dbh->prepare("DELETE FROM $this->table_name Where id = :id"); $stmt->bindValue(':id', (int)$id, \PDO::PARAM_INT); $stmt->execute(); echo 'ブログを削除しました!'; return $result; } //} ?> 度々申し訳ございません。 教えてください。 ご回答のほど宜しくお願い申し上げます。

    • ベストアンサー
    • PHP
  • PDOクラスのprepareメソッドについて。

    いつもお世話になっております。 PHP5.2.5 1|$conn = new PDO($dsn,~略~);   //データベース接続 2|$sql = "略";             //SQL文 3|$stmt = $conn->prepare($sql);   // PDOStatementオブジェクトを返す 4|$stmt->bindParam(~略~);     //プレースホルダに変数をバインド 5|$stmt->execute();         //クエリ実行 という、よくある流れにおいて、 4行目のbindParamメソッドは、PDOクラスのメソッドではなく、 PDOStatementクラスのメソッドだと思うのですが、 これを、$stmt-> で呼び出せているのが、どうしてなのかがよく分からずにいます。 3行目で、PDOクラスのprepareメソッドを使うことで、 PDOStatementオブジェクトが返されるため、 その返り値を受け取った「$stmt」によって、 「$stmt->bindParam」できているという感じでしょうか? ★まず、この私の考え方について、合っているか間違っているか、 お聞きしたいと思います。(質問1) //=================================================== 恐らく、上記の考え方は「合っている」のだと思うのですが、 その上で、さらに質問をさせて頂くと、 ではなぜ、PDOStatementクラスを使う時に、 new PDOStatement; というようにしないのでしょうね? PDOクラスの1メソッドであるprepareメソッドを使うようにして、 PDOStatementクラスをインスタンス化しているのはなぜなのでしょう? (prepareメソッドはどういうコードになっているのでしょう?その中で、new PDOStatement という記述があるのでしょうね?) PDOのこのような仕様の背景には、どういう意図があるのか、 どなたか何か思い当たることなどありましたらご助言下さい。 (質問2)

    • ベストアンサー
    • PHP
  • SQLインジェクション対策

    SQLインジェクション対策として、変数を直接SQLに埋め込むのではなく、PDOのprepareメソッドを利用して作成したステートメントに値をバインドする形式にする場合、ユーザー定義関数をどのように 修正すればいいですか? function update_item_stock($db, $item_id, $stock){ $sql = " UPDATE items SET stock = {$stock} WHERE item_id = {$item_id} LIMIT 1"; return execute_query($db, $sql); } function execute_query($db, $sql, $params = array()){ try{ $stmt = $db->prepare($sql); return $stmt->execute($params); }catch(PDOException $e){ set_error('更新に失敗しました。'); } return false; } 上記のユーザー定義関数を下記のようにbindValueを用いて表す場合、$stmt->bindValueの部分を 上記のどこに追加すればいいですか? try { $sql = 'UPDATE item_stock SET stock = ?, update_date = ? WHERE item_id = ?'; $stmt = $db->prepare($sql); $stmt->bindValue(1, $update_stock, PDO::PARAM_INT); $stmt->bindValue(2, $date, PDO::PARAM_STR); $stmt->bindValue(3, $item_id, PDO::PARAM_INT); $stmt->execute(); $complete_msg[] = '在庫変更に成功しました。'; } catch (PDOException $e) { $err_msg[] = '更新に失敗しました。理由:' . $e->getMessage(); }

    • 締切済み
    • PHP
  • biginTransaction();でエラー??

    いつも大変お世話になり誠にありがとうございます。 私は、おっしゃる通り、理解しながらやっていないです。 でも、自分なりに理解できるところは為になっております。 皆様のおかげです。 標記の件。 エラーメッセージは ( ! ) Fatal error: Uncaught Error: Call to undefined method PDO::biginTransaction() in /srv/www/htdocs/blog.php on line 30 ( ! ) Error: Call to undefined method PDO::biginTransaction() in /srv/www/htdocs/blog.php on line 30 です。 どう直せばいいでしょうか? どうか教えてください。 宜しくお願い申し上げます。      記 <?php require_once('dbc.php'); class Blog extends Dbc { protected $table_name = 'blog'; //カテゴリー名を表示 //引数:数字 //返り値:カテゴリーの文字列 public function setCategoryName($category) { if ($category == '1') { return '日常'; } elseif ($category == '2') { return '非日常'; } else { return 'その他'; } } public function blogCreate($blogs) { $sql = "INSERT INTO blog(title,content,category,publish_status) VALUES (:title, :content, :category, :publish_status)"; $dbh = $this->dbConnect(); $dbh->biginTransaction(); try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':title', $blogs['title'], PDO::PARAM_STR); $stmt->bindValue(':content', $blogs['content'], PDO::PARAM_STR); $stmt->bindValue(':category', $blogs['category'], PDO::PARAM_INT); $stmt->bindValue(':publish_status', $blogs['publish_status'], PDO::PARAM_INT); $stmt->bindValue(':id', $blogs['id'], PDO::PARAM_INT); $stmt->execute(); $stmt->commit(); echo 'ブログを投稿しました!'; } catch (PDOException $e) { $dbh->rollBack(); exit($e); } function blogUpdate($blogs) { $sql = "UPDATE $this->table_name SET title = :title, content = :content, category = :category, publish_status = :publish_status Where id = :id"; $dbh = dbConnect(); $dbh->biginTransaction(); try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':title', $blogs['title'], PDO::PARAM_STR); $stmt->bindValue(':content', $blogs['content'], PDO::PARAM_STR); $stmt->bindValue(':category', $blogs['category'], PDO::PARAM_INT); $stmt->bindValue(':publish_status', $blogs['publish_status'], PDO::PARAM_INT); $stmt->bindValue(':id', $blogs['id'], PDO::PARAM_INT); $stmt->execute(); $stmt->commit(); echo 'ブログを更新しました!'; } catch (PDOException $e) { $dbh->rollBack(); exit($e); } } function blogUpdate($blogs){ } //ブログのバリデーション function blogValidate($blogs) { if (empty($blogs['title'])) { exit('タイトルを入力してください。'); } if (mb_strlen($blogs['title']) > 191) { exit('タイトルは191文字以下にしてください。'); } if (empty($blogs['content'])) { exit('本文を入力してください。'); } if (empty($blogs['category'])) { exit('カテゴリーは必須です。'); } if (empty($blogs['publish_status'])) { exit('公開ステータスは必須です。'); } } } } ?>

    • ベストアンサー
    • PHP

専門家に質問してみよう