パラメータ化されたSELECTクエリにPDOオブジェクトを適切に使用するにはどうすればよいですか


85

PHP.netの指示に従ってみました SELECTクエリを実行の最善の方法がません。

SELECT可能であれば、パラメータ化されたクエリを使用してIDnameフィールドがパラメータと一致するテーブルでを返したいと思います。これはID一意になるため、1つを返す必要があります。

私はそれを使用するように、その後希望IDのためにINSERT別のテーブルに、私はそれが成功したかどうかを決定する必要があります。

また、クエリを再利用できるように準備できることも読みましたが、これがどのように役立つかはわかりませんでした。

回答:


158

次のようなデータを選択します。

$db = new PDO("...");
$statement = $db->prepare("select id from some_table where name = :name");
$statement->execute(array(':name' => "Jimbo"));
$row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator

同じ方法で挿入します。

$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));

エラー時に例外をスローするようにPDOを構成することをお勧めします。PDOExceptionクエリのいずれかが失敗した場合は、を取得します-明示的にチェックする必要はありません。例外をオンにするには、$dbオブジェクトを作成した直後にこれを呼び出します。

$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

新しいPDO(...)があるPDOStatementを意味していると思いますよね?
ジョーフィリップス

1
番号。PDOは接続クラスです(代わりにPdoConnectionという名前が付けられているはずです)。接続により、PdoStatementsを作成できます。個々のステートメントではなく、接続オブジェクトでsetAttribute()を呼び出します。(または、コンストラクターに渡すこともできます)
troelskn 2009

1
これは役に立つかもしれません:$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');
ジュニアメイヘム2012

2
ライン$statement->execute(array(':name' => "Jimbo"));については、ジンボの部分を説明していただけますか?
muttley91 2012

1
@rar前の行では、クエリはプレースホルダーで開始されています:nameexecuteここでの呼び出しは、プレースホルダー->値のペアの連想配列を使用して行われます。したがって、この場合、:nameプレースホルダーは文字列Jimboに置き換えられます。値はエスケープされるか、実際のクエリとは異なるチャネルを介して送信されるため、単純に文字列置換を行うのではなく、あらゆる種類のインジェクション攻撃を防ぐことに注意してください。
troelskn 2012

16

私は最近PDOを使用していて、上記の答えは完全に正しいですが、次のことも機能することを文書化したかっただけです。

$nametosearch = "Tobias";
$conn = new PDO("server", "username", "password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
$sth->bindParam(':name', $nametosearch);
// Or sth->bindParam(':name', $_POST['namefromform']); depending on application
$sth->execute();

16
いいえ、使用するデータベースを選択していないため、選択されません。
Rápliアンドラーシュ

3
これは実際には「server」文字列に含まれている必要があります。これは実際には「{driver}:dbname = {db_name}; host = {server}」の形式のDSNであり、中括弧の値を接続に必要なものに置き換えます
thorne51

12

bindParamまたはbindValueメソッドを使用して、ステートメントの準備に役立てることができます。$check->execute(array(':name' => $name));特に複数の値/変数をバインドしている場合は、実行する代わりに一目で物事がより明確になります。

以下の明確で読みやすい例を確認してください。

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetch(PDO::FETCH_ASSOC);
    $row_id = $check['id'];
    // do something
}

複数の行が予想される場合は、LIMIT 1を削除し、フェッチメソッドをfetchAll次のように変更します。

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetchAll(PDO::FETCH_ASSOC);
    //$check will now hold an array of returned rows. 
    //let's say we need the second result, i.e. index of 1
    $row_id = $check[1]['id']; 
    // do something
}

わからない。私には有効な答えのようです。'name'の代わりに 'myname'を使用し、1つではなく複数のparamsを使用することでメリットが得られると思います。
ジョーフィリップス

@GillianLoWong何をし$check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something }ますか?
アブドゥル

1
こんにちは@abdul、配列のカウント/空のチェックを置き換えました。結果が返されるかどうかを確認することになっています。ただし、pdoにはrowCount()という関数もあり、影響を受けた/フェッチされた行があるかどうかを確認できます。行が選択されているかどうかさえわからない場合は、データをフェッチしても意味がないため、fetchステートメントをif rowCount()ステートメントに移動しました。:)
Gilly 2015年

@Gillian La Wongは、複数のwhereクエリに対するbindValueのクリーンなクエリに感謝します。それは私のプロジェクトを救います。
php-coder

6

少し完全な答えがここにあり、すべて使用できる状態になっています。

    $sql = "SELECT `username` FROM `users` WHERE `id` = :id";
    $q = $dbh->prepare($sql);
    $q->execute(array(':id' => "4"));
    $done= $q->fetch();

 echo $done[0];

これ$dbhがPDOdbコネクタであり、id、テーブルから次のusersようになります。username使用をfetch();

これが誰かの助けになることを願っています、お楽しみください!


またはfetchColumn()[0]必要になるのを避けるために使用します。また、LIMIT 1SQLで使用することを忘れないでください。
rybo111 2016

3

方法1:USEPDOクエリメソッド

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

行数の取得

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

方法2:パラメーターを含むステートメント

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->execute(array($name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

方法3:パラメーターをバインドする

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

**bind with named parameters**
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

or
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->execute(array(':name' => $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

このリンクをもっと知りたい


4
方法1を削除してください。mysqlインジェクションが可能です。
トマホック2016

-2

単一ページでインラインコーディングを使用していて、この完全な例を使用するよりもoopsを使用していない場合は、確実に役立ちます

//connect to the db
$dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw); 

//build the query
$query="SELECT field1, field2
FROM ubertable
WHERE field1 > 6969";

//execute the query
$data = $dbh->query($query);
//convert result resource to array
$result = $data->fetchAll(PDO::FETCH_ASSOC);

//view the entire array (for testing)
print_r($result);

//display array elements
foreach($result as $output) {
echo output[field1] . " " . output[field1] . "<br />";
}

このコードスニペットは問題を解決する可能性がありますが、質問に答える理由や方法については説明していません。投稿の品質を向上させるのに役立つので、コードの説明を含めてください。あなたは将来読者のために質問に答えていることを忘れないでください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。フラグ作成者/レビュー担当者: このようなコードのみの回答の場合は、反対票を投じて、削除しないでください。
スコットウェルドン

だから私はそれを自分で削除する必要があります
Shiv Singh

いいえ、正反対です。Low Quality Posts Queueでこの投稿に出くわしたので、コメントの後半は、削除に投票しないように人々に指示することでした。(代わりに反対票を投じる提案は、暫定的な反対票を促すことを目的としており、投稿が編集された後に削除されます。)以前のコメントで述べたように、あなたが行ったコードを提案した理由の説明を追加した方がよいでしょう。 。また、この質問はパラメータfield > 6969化されたクエリについて尋ねますが、パラメータ化されているのではなくハードコードされているように見えます。
スコットウェルドン2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.