Pdo はクエリを実行せずにパラメータを置換します。 PDO を使用するにはどうすればよいですか? 完全なガイド。 データベースへの挿入、exec() メソッド

データベース接続 PDO クラスのインスタンスが作成されるときに設定されます。 どのドライバーを使用するかは重要ではありません。 常に PDO クラスを使用する必要があります。 そのコンストラクターは、データベース ソース (DSN と呼ばれる) を指定するパラメーターと、ユーザー名とパスワードのオプションのパラメーターを受け入れます。

MySQL への接続:

$dbh = 新しい PDO("mysql:host=localhost;dbname=test", $user, $pass);

接続エラーが発生すると、PDOException クラスのオブジェクトという例外がスローされます。 この状況を処理したい場合は、それをキャッチすることも、set_Exception_handler() で設定されるグローバル例外ハンドラーに任せることもできます。

接続エラーの処理:

try ( $dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass); foreach($dbh->query('SELECT * from FOO') as $row) ( print_r($ row); ) $dbh = null; ) catch (PDOException $e) ( die("エラー! 以上です。到着しました... ".$e->getMessage()); )

注意: PDO コンストラクターによってスローされた例外をキャッチしない場合、zend エンジンによって実行されるデフォルトのアクションは、スクリプトを停止してトレースバックを表示することです。 このがらくたは、データベースとの通信に関するすべての親密な詳細を明らかにします。 あれは ユーザー名とパスワードを含むデータベース接続の詳細が表示されます。この例外を明示的に(ステートメント経由で)キャッチするかどうかはあなた次第です。 キャッチしてみてください)、または set_Exception_handler() を介して暗黙的に。

データベース接続が成功すると、PDO オブジェクト インスタンスの存続期間中、データベース接続はアクティブなままになります。 接続を閉じるには、オブジェクトを破棄し、そのオブジェクトへの残りの参照がすべて削除されるようにする必要があります。これは、オブジェクトを含む変数に値 NULL を割り当てることで実行できます。 これを明示的に行わないと、スクリプトの終了時に PHP が自動的に接続を閉じます。

接続を閉じる:

$dbh = 新しい PDO("mysql:host=localhost;dbname=test", $user, $pass); // ここで何かをしています: ... // ここで注意: 接続は終了です! $dbh = null;

多くの Web アプリケーションは、データベース サーバーへの永続的な接続を作成することで恩恵を受けます。 永続的な接続は、スクリプトの終了時に閉じられませんが、別のスクリプトが同じ接続資格情報を使用して接続を要求したときにキャッシュされ、再利用されます。 永続的な接続キャッシュにより、スクリプトがデータベースと通信する必要があるたびに新しい接続を確立するオーバーヘッドが回避され、Web アプリケーションの実行が高速化されます。

永続的な接続のセットアップ:

$dbh = 新しい PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

留意してください:永続的な接続を使用する場合は、次のように設定する必要があります。 PDO::ATTR_PERSISTENTドライバー オプション配列内で、PDO クラス コンストラクターに渡されます。 オブジェクトがインスタンス化された後に PDO::setAttribute() を介してこの属性を設定すると、ドライバーは永続リンクを使用しなくなります。 また、この場合、一部のニーズに合わせて PDOStatement クラスを拡張することはできません。 以下の場合はインストールできなくなります。 PDO::ATTR_STATEMENT_CLASS

経験を積み、データベースを扱うときに mysql_ 関数から PDO に切り替える時期が来たと思います。 このライブラリは、PHP への強力かつ高速な追加機能です。 その利点の 1 つは、多くのデータベース (MS SQL、MySQL、PostgreSQL、Oracle など) で動作することです。 また、このライブラリの独特の特徴は、準備された式、いわゆる準備されたステートメントです。これにより、データベースでの作業が高速化され、最も重要なことに、データ交換が安全になり、SQL インジェクションなどの脆弱性が忘れられます。 さらに、他にも非常に便利な機能があります。 この記事では、PDO業務の本質がすぐにわかる、よく使われる業務事例を集めてみました。

PHP には、MySQL データベースを操作するための 3 つの拡張機能 (mysql、mysqli、PDO) があります。 PHP PDO (PHP Data Objects) は、PHP 5.1 以降に含まれています。 私の理解では、php_mysql の開発は MySQL 4.1.3 の機能のサポートで終了しているため、現時点では mysql_ データベースを操作する関数の使用は推奨されていません。 また、トランザクションやオブジェクト インターフェイスもサポートしておらず、クエリに値を代入する際に脆弱性があります。 mysql_ の後に、mysqli 拡張機能 (バージョン 5 で改良された MySQL) が登場しました。これは、新しい MySQL 機能をサポートし、OPP 構文と手続き型プログラミングの両方を使用します。 これらのライブラリはすべて、標準の MySQL クライアント ライブラリ (libmysql) を使用します。 同じメモで、最新の拡張機能を使用して mysql を操作する方法の実際の例を見てみましょう。 PDO.

PDOデータベース接続

//PDO を使用して MySQL に接続する例 $db = new PDO("mysql:host=localhost;dbname=test", $user, $pass);

特定のデータベース サーバーへの接続が正常に確立されると、PDO オブジェクトが返されます。 このオブジェクトを使用すると、さまざまなデータベース タスクを実行できます。

接続エラーがある場合、例外メカニズム PDOException がトリガーされます。 PDO 操作は常に try/catch ブロックでラップする必要があります。 エラーを処理したい場合は例外をキャッチすることも、set_Exception_handler() で作成したグローバル例外ハンドラーに例外を残しておくこともできます。 PDO にはエラー用の特別な関数があります。errorCode() – エラー番号を返します。errorInfo() – エラー番号と説明を含む配列を返します。 デフォルトのエラー処理モードが ERRMODE_SILENT であるため、これらが必要になります。 この場合、これらのエラーを確認するには、次のように呼び出す必要があります。

エコー $conn->errorCode(); echo $conn->errorInfo();

これを回避するには、開発モードで目的のエラー処理モード (ATTR_ERRMODE および ERRMODE_EXCEPTION) をすぐに設定する方が簡単です。 データベースを操作するためのエンコーディングを指定することもできます。 その結果、次の接続コードが得られます。

Try ( $db = new PDO("mysql:host=$host;dbname=$dbname", $user, $password); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db-> exec("set names utf8"); ) catch(PDOException $e) ( echo $e->getMessage(); )

データベースへの接続に成功すると、PDO クラスのインスタンスがスクリプトに返されます。 $db にはデータベース ハンドルが含まれます。 接続は PDO オブジェクトの存続期間中アクティブのままです。 接続を閉じるには、オブジェクトを破棄し、そのオブジェクトへの他のすべての参照が確実に削除されるようにする必要があります。 これを行うには、オブジェクトを含む変数を NULL に割り当てます。 これを明示的に行わない限り、スクリプトの完了時に PHP は自動的に接続を閉じます。

//接続を閉じます $db = null;

多くの Web アプリケーションは、データベース サーバーへの永続的な接続を作成することで恩恵を受けます。 永続的な接続はスクリプトの終了時に閉じられませんが、別のスクリプトが同じ資格情報を使用して接続を要求したときにキャッシュされ、再利用されます。 永続的な接続により、スクリプトがデータベースにアクセスする必要があるたびに新しい接続を作成するオーバーヘッドが軽減され、Web アプリケーションが高速化されます。

//永続的な接続 $dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

接続を開いたり閉じたりする方法を理解したので、PDO を使用した他の例を見てみましょう。 今回は、特定のデータベースにクエリを実行する方法を説明します。 クエリは、exec()、query()、prepare+execute の 3 つの関数を使用して作成できます。

実行()

最初の - exec は、関係する行数のみを返すか、エラーの場合は FALSE を返し、データが返されない場合 (削除時など) に使用されます。

//exec() メソッドを使用する try( $db = new PDO("mysql:host=localhost;dbname=test","user","password"); $delrows=$db->e​​xec("ユーザーから削除WHERE id>20"); echo "削除された行数: ".$delrows; ) catch(PDOException $e)( echo "エラー: ".$e->getMessage(); exit(); ) //More $ db->e​​xec("WHERE 1 の人々から削除"); //または $db->e​​xec("SET time_zone = "-8:00""); //または $db->e​​xec("CREATE TABLE `test`(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL DEFAULT "", email VARCHAR(50) NOT NULL DEFAULT "")"); //または $db->e​​xec("SET CHARACTER SET utf8");

クエリ()

次に、query() は結果を PDOStatement オブジェクトで返します。 また、結果またはエラー時に FALSE を返します。 簡単なリクエストなら彼を信頼できます。 query() を条件付きで使用することはできますが (なぜこれが必要になるのか本当にわかりません)、その場合でも PDO::quote メソッドを使用してデータをエスケープする必要があります。

// 単純なクエリ $db->query("SET CHARACTER SET utf8"); $db->query("SELECT * FROM ユーザー"); //行数を計算できます $stmt = $db->query("SELECT * FROM table"); $row_count = $stmt->rowCount(); echo $row_count." 行が選択されました"; //数量を伴う別のオプション $stmt = $db->query("SELECT * from users"); $rows = $stmt->fetchAll(); $count = count($rows); foreach($rows as $row) ( print_r($row); ) // 条件とエスケープを使用したクエリ $conn->query("SELECT * FROM table WHERE id = " . $conn->quote($id));

lastInsertId()最後に挿入されたデータベース行の ID を返します。

// lastInsertId() メソッドは最後のレコードの ID を返します $db->query("INSERT INTO users SET name="Vasya",address="Here",email=" [メールで保護されています]""); $insertId=$db->lastInsertId();

準備されたステートメント。

第三の道 - 準備+実行 - 準備された式、それらは準備された命令でもあり、プレースホルダーでもあり、それらは 準備されたステートメントまたはバインド変数を使用すると、式を 1 回定義して、それをさまざまなパラメーターを使用して複数回実行できます。 また、変数をリクエストから分離することもできるため、コードの安全性が高まり、実行速度が向上します。 コードは転送中のデータをクリーンアップしようとする必要がなくなります。 これは、データベース クエリを実行する前に 1 回だけ実行します。 これを行うには、関数を使用します 準備する(); SQL クエリをパラメータとして受け取りますが、変数の代わりに、疑問符「?」または数字「:1」、または名前がコロン「:」で始まる変数の形式でラベルが使用されます。 。 疑問符 (:numbers) で停止した場合は、適切な順序で値の配列を実行関数に渡す必要があります。 名前付き変数を選択した場合は、2 つの関数のいずれかを使用して各変数に値を割り当てる必要があります。bindValue() は疑似変数に値を割り当てるか、bindParam() は疑似変数をバインドします。実数変数。 3 番目のパラメーターは変数のタイプを示すことができます (例: $db->bindParam(':id',$id, PDO::PARAM_INT))。

//名前のないラベル try ( $stmt = $db->prepare("INSERT INTO test (label,color) VALUES (?,?)"); $stmt ->execute(array("perfect","green") ) ; ) catch(PDOException $e)( echo "Error: ".$e->getMessage(); exit(); ) //stmt は「状態ハンドル」です //名前付きラベル $stmt = $db->prepare ( "INSERT INTO test (label,color) VALUES (:label,:color)"); $stmt ->execute(array("label"=>"perfect", "color"=>"green")); //別のオプション $stmt = $db->prepare("INSERT INTO users (firstname, lastname, email) VALUES (:firstname, :lastname, :email)"); $stmt->bindParam(":firstname", $firstname); $stmt->bindParam(":lastname", $lastname); $stmt->bindParam(":email", $email); $firstname = "ジョン"; $lastname = "スミス"; $メール = " [メールで保護されています]"; $stmt->execute();

準備された式を使用しないが、送信されたデータを保護したい場合は、PDO:quote 関数を使用してこれを行うことができることをもう一度思い出させてください。

PDO SELECT データ

fetch() または fetchAll() メソッドは、データの取得に使用されます。 関数を呼び出す前に、データベースからデータを取得する方法を PDO に指示する必要があります。 PDO::FETCH_ASSOC は、フィールド名をキーとした連想配列として行を返します。 PDO::FETCH_NUM は文字列を数値配列として返します。 デフォルトでは、フェッチは PDO::FETCH_BOTH で行われ、数値キーと連想キーの両方でデータが複製されるため、配列の重複を避けるために 1 つの方法を指定することをお勧めします。

$stmt = $db->query("SELECT * ユーザーから"); //フェッチモードの設定 $stmt->setFetchMode(PDO::FETCH_ASSOC); while($row = $stmt->fetch()) ( echo "

" . $row["firstname"] . " " . $row["lastname"] . "

"; エコー "

" . $row["email"] . "


"; }

または、 ->fetch() メソッド自体でフェッチ メソッドを指定することもできます。

$stmt = $db->query("SELECT * FROM table"); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) ( echo $row["field1"]." ".$row["field2"]; //etc... ) // 注意、 LIKE を使用した例は機能しません。 $stmt = $db->prepare("SELECT フィールド FROM テーブル WHERE フィールド LIKE %?%"); $stmt->bindParam(1, $search, PDO::PARAM_STR); $stmt->execute(); //これが必要です: $stmt = $db->prepare("SELECT field FROM table WHERE field LIKE ?"); $stmt->bindValue(1, "%$search%", PDO::PARAM_STR); $stmt->execute(); //別の例 $stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?"); $stmt->bindValue(1, $id, PDO::PARAM_INT); $stmt->bindValue(2, $name, PDO::PARAM_STR); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); //別のオプション $stmt = $db->prepare("SELECT * from users"); $stmt -> 実行(); while($row = $stmt->fetch()) ( print_r($row); )

PDOアップデートデータ

これは基本的に INSERT および SELECT と同じ方法で行われます (この場合も名前付きプレースホルダーを使用します)。

$stmt = $db->prepare("UPDATE users set email = :email where lastname=:lastname"); $stmt->bindParam(":lastname", $lastname); $stmt->bindParam(":email", $email); $lastname = "スミス"; $メール = " [メールで保護されています]"; $stmt->execute();

消去削除は最も簡単な方法で行われます。

$db->e​​xec("ユーザーから削除");

もちろん、削除するときに名前付きプレースホルダーを使用することもできます。

PHP PDO 拡張機能を使用する際に頻繁に使用する独自のテンプレートをお持ちの場合は、共有していただければ幸いです。 マニュアルへのリンク

「未定義の変数: DBH...」というエラーが発生した場合は、それを修正する方法を読むことができます。

Google は PDO に関するチートシートを見つけるのに協力してくれました。おそらく誰かが役立つと思うでしょう:

PDO (PHP Data Objects) は、オブジェクトを使用したデータベースとの対話を実装する PHP 拡張機能です。 利点は、特定のデータベース管理システムに接続しないことです。 PDO は、MySQL、PostgreSQL、SQLite、Oracle、Microsoft SQL Server などの DBMS をサポートします。

PDO を使用する理由

データベースを操作するための PHP の mysql 関数は時代遅れになって久しいため、現在では mysqli または PDO (PHP データ オブジェクト) を使用することをお勧めします。 さらに、mysqli は、概してコード内で直接使用することを目的としたライブラリではありません。 より高いレベルのライブラリを作成するための優れた建築材料として機能します。 mysqli を使用する場合は、アプリケーションのセキュリティ、特に SQL インジェクションに対する保護を確保することも忘れないでください。 PDO (準備されたクエリを含む) を使用する場合、そのような保護はすぐに利用できますが、重要なことは、必要なメソッドを正しく適用することです。

テーブルを使用してデータベースをテストする

// Windows コンソールから mysql> CREATE DATABASE `pdo-test` CHARACTER SET utf8 COLLATE utf8_general_ci; pdo-test を使用します。 CREATE TABLE カテゴリ (id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT、PRIMARY KEY(id)、name VARCHAR(255) NOT NULL); INSERT INTO `カテゴリ` (`名前`) 値 (「ラップトップとタブレット」)、(「コンピュータと周辺機器」)、(「PC コンポーネント」)、(「スマートフォンとスマート ウォッチ」)、(「テレビとメディア」) 、(「ゲーム機およびゲーム機」)、(「オーディオ機器」)、(「写真およびビデオ機器」)、(「オフィス機器および家具」)、(「ネットワーク機器」)、(「大型家電製品」)、( 「キッチン用品」)、(「美容と健康」)、(「家庭用品」)、(「工具」)、(「自動車用品」);

PDOのインストール

// Linux へのインストール sudo apt update sudo apt install php7.2-mysql sudo apt-get install pdo-mysql // php.ini に extension=pdo.so extension=pdo_mysql.so を追加 // Windows では、原則として、ドライバーはすでにインストールされています。php.ini extension=php_pdo_mysql.dll でドライバーが有効になっているかどうかを確認するだけです。

利用可能なドライバーを確認する

print_r(PDO::getAvailableDrivers());

データベース接続

PDO オブジェクトがその基本クラスから作成されると、接続は自動的に確立されます。

// 例 1。 シンプルな接続 $db = new PDO("mysql:host=localhost;dbname=pdo", "root", "password");

接続エラーがある場合、PHP はエラーをスローします。

致命的なエラー: キャッチされない PDOException: ... // 例 2。 接続エラーの処理 try ( $dbh = new PDO("mysql:host=localhost;dbname=pdo", "root", "password"); ) catch (PDOException $e) ( print "Error!: " . $e- >getMessage(); die(); )

この接続例では、try...catch コンストラクトを使用します。 その使用の妥当性については多くの人が議論しています。 個人的には、 try...catch を使用しますが、気にしません。

準備されたリクエストと直接のリクエスト

PDO でクエリを実行するには 2 つの方法があります。

  • 直接 - 1 つのステップで構成されます。
  • 準備済み - 2 つのステップで構成されます。

直接リクエスト

  • query() は、SELECT などの変更を行わないステートメントに使用されます。 fetch() または fetchAll メソッドを使用してクエリ結果が取得される PDOStatemnt オブジェクトを返します。 これを、mysql_query() によって返された mysql リソースと比較できます。
  • exec() は、INSERT、DELETE、UPDATE ステートメントに使用されます。 リクエストによって処理された行数を返します。

直接クエリは、クエリ内に変数がなく、クエリが安全で適切にエスケープされていると確信できる場合にのみ使用されます。

$stmt = $db->query("SELECT * FROM カテゴリ"); while ($row = $stmt->fetch()) ( echo "

"; print_r($row); )

準備されたクエリ

少なくとも 1 つの変数がリクエストに渡される場合、このリクエストは準備された式を通じてのみ実行される必要があります。 それはどういう意味ですか? これは通常の SQL クエリで、変数の代わりに特別なマーカー (プレースホルダー) が配置されます。 PDO は、渡される変数の順序が重要な位置プレースホルダー (?) と、順序が重要でない名前付きプレースホルダー (:name) をサポートします。 例:

$sql = "カテゴリーから名前を選択 WHERE id = ?"; $sql = "カテゴリから名前を選択 WHERE name = :name";

このようなクエリを実行するには、まず prepare() メソッドを使用してクエリを準備する必要があります。 また、PDO ステートメントも返しますが、まだデータはありません。 それらを取得するには、事前に変数を渡してこのリクエストを実行する必要があります。 これは 2 つの方法で渡すことができます。ほとんどの場合、単にexecute() メソッドを実行し、変数を含む配列を渡します。

$stmt = $pdo->prepare("SELECT `name` FROM カテゴリ WHERE `id` = ?"); $stmt->execute([$id]); $stmt = $pdo->prepare("SELECT `name` FROM カテゴリ WHERE `name` = :name"); $stmt->execute(["name" => $name]);

ご覧のとおり、名前付きプレースホルダーの場合、キーがプレースホルダーの名前と一致する必要がある配列を、execute() に渡す必要があります。 その後、クエリ結果を取得できます。

$id = 1; $stmt = $db->prepare("SELECT * FROM カテゴリ WHERE `id` = ?"); $stmt->execute([$id]); $category = $stmt->fetch(PDO::FETCH_LAZY); エコー "

"; print_r($category);

重要!プリペアド クエリは、変数を含む SQL クエリを実行する唯一の安全な方法であるため、PDO を使用する主な理由です。

データ受信中。 fetch() メソッド

fetch() メソッドについてはすでに説明しました。このメソッドは、データベースから行を順番に取得するために使用されます。 このメソッドは、mysq_fetch_array() 関数や同様の関数に似ていますが、動作が異なります。ここでは多くの関数の代わりに 1 つの関数が使用されていますが、その動作は渡されたパラメータによって指定されます。 これらのパラメータの詳細については後述します。簡単な推奨事項として、FETCH_LAZY モードで fetch() を使用することをお勧めします。

$id = 1; $stmt = $db->prepare("SELECT * FROM カテゴリ WHERE `id` = ?"); $stmt->execute([$id]); while ($row = $stmt->fetch(PDO::FETCH_LAZY)) ( echo "カテゴリ名: ".$row->name; )

このモードでは、余分なメモリが無駄にならず、さらに、インデックス、名前、またはプロパティ (-> 経由) の 3 つの方法のいずれかで列にアクセスできます。 このモードの欠点は、fetchAll() では機能しないことです。

データ受信中。 fetchColumn() メソッド

PDO ステートメントには、単一列の値を取得するメソッドもあります。 フィールドを 1 つだけリクエストする場合は非常に便利です。この場合、コードの量が大幅に削減されます。

$id = 1; $stmt = $db->prepare("SELECT `name` FROM カテゴリ WHERE `id` = ?"); $stmt->execute([$id]); $name = $stmt->fetchColumn(); echo "カテゴリ名: ".$name;

データ受信中。 fetchAll() メソッド

$data = $db->query("SELECT * FROM category")->fetchAll(PDO::FETCH_ASSOC); foreach ($data as $k => $v)( echo "カテゴリ名: ".$v["name"]."
"; }

PDO と LIKE 演算子

準備されたクエリを使用する場合は、プレースホルダーで置き換えることができることを理解する必要があります。 のみ文字列または数値。 キーワードでも識別子でも、文字列またはプレースホルダーを介した文字列セットの一部でもありません 代わりはできません。 したがって、LIKE の場合は、まず検索文字列全体を準備してから、それをクエリに置き換える必要があります。

$search = "コンプ"; $query = "SELECT * FROM カテゴリ WHERE `name` LIKE ?"; $params = ["%$search%"]; $stmt = $db->prepare($query); $stmt->execute($params); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); $i = 1; foreach ($data as $category)( echo $i++ . ". " . $category["name"]."
"; }

ここで問題が発生する可能性があります。 データベースから間違ったエンコードでデータを受信して​​いるため、検索が機能しない可能性があります。 そこにエンコーディングがリストされていない場合は、接続にエンコーディングを追加する必要があります。

$db = 新しい PDO("mysql:host=localhost;dbname=pdo;charset=utf8", "root", "");

PDO と LIMIT 演算子

重要! PDO がエミュレーション モードで実行されている場合、execute() に直接渡されたすべてのデータは文字列としてフォーマットされます。 つまり、エスケープされ、引用符で囲まれます。 だからLIMIT?、? は LIMIT "10", "10" になり、明らかに構文エラーが発生し、それに応じて空のデータ配列が発生します。

解決策 #1: エミュレーション モードを無効にする:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

解決策 #2:bindValue() を使用してこれらの数値をバインドし、強制的に PDO::PARAM_INT タイプになります。

$limit = 3; $stm = $db->prepare("SELECT * FROM カテゴリ LIMIT ?"); $stm->bindValue(1, $limit, PDO::PARAM_INT); $stm->execute(); $data = $stm->fetchAll(); エコー "

"; print_r($data);

PDO および IN 演算子

テーブルから選択する場合、配列のすべての値に対応するレコードを取得する必要があります。

$arr = ; $in = str_repeat("?,", count($arr) - 1) 。 「?」 $sql = "SELECT * FROM カテゴリ WHERE `id` IN ($in)"; $stm = $db->prepare($sql); $stm->execute($arr); $data = $stm->fetchAll(); エコー "

"; print_r($data);

エントリの追加

$name = "新しいカテゴリ"; $query = "`カテゴリ` (`名前`) 値 (:名前) に挿入"; $params = [ ":name" => $name ]; $stmt = $pdo->prepare($query); $stmt->execute($params);

エントリの変更

$id = 1; $name = "変更されたエントリ"; $query = "UPDATE `カテゴリ` SET `name` = :name WHERE `id` = :id"; $params = [ ":id" => $id, ":name" => $name ]; $stmt = $pdo->prepare($query); $stmt->execute($params);

エントリの削除

$id = 1; $query = "`カテゴリ` WHERE `id` = ?から削除します。"; $params = [$id]; $stmt = $pdo->prepare($query); $stmt->execute($params);

トランザクションの使用

try ( // トランザクションの開始 $pdo->beginTransaction(); // ... code // コードを実行した結果、すべてが成功した場合、 // この結果を記録します $pdo->commit() ; ) catch (Exception $e) ( // それ以外の場合は、トランザクションをロールバックします。 $pdo->rollBack(); echo "Error: " . $e->getMessage(); )

重要! PDO のトランザクションは InnoDB テーブルでのみ機能します

この記事では、PDO の基本概念、そのインストール、データベースへの接続、およびデータの選択、変更、削除のための最も簡単なオプションについて説明しました。 今後の投稿では、PDO に関連するトピックをさらにいくつか取り上げていきます。

生産性を高めるための式を準備し、オブジェクトを操作するためのメソッドを提供します。

PDO の概要

「PDO - PHP データ オブジェクトは、さまざまなデータベースにアクセスするための統一された方法を提供するデータベース アクセス層です。」

特定のデータベース構文に依存せず、ほとんどの場合、接続文字列を変更するだけで別のデータベース タイプやプラットフォームに簡単に切り替えることができます。

このレッスンは、作業プロセスについて説明するものではありません。 SQL。 拡張機能を使用する人向けです mysqlまたは ミスクリより強力でポータブルな PDO への移行を支援します。

データベースのサポート

この拡張機能は、PDO ドライバーが存在するあらゆるデータベースをサポートします。 現在、ドライバーは次のデータベース タイプで利用できます。

  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (ファイアバード/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix 動的サーバー)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle 呼び出しインターフェース)
  • PDO_ODBC (ODBC v3 (IBM DB2、unixODBC、および win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 および SQLite 2)
  • PDO_4D (4D)

システムが動作するには、本当に必要なドライバーのみをインストールするだけで十分です。 次のようにして、システムで利用可能なドライバーのリストを取得できます。

Print_r(PDO::getAvailableDrivers());

繋がり

データベースが異なると、接続方法が若干異なる場合があります。 いくつかの一般的なデータベースに接続する方法を以下に示します。 最初の 3 つは互いに同一であり、SQLite のみが特定の構文を持っていることがわかります。


try ( # PDO_DBLIB を使用した MS SQL Server と Sybase $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass"); $DBH = new PDO("sybase:host=$host) ;dbname=$dbname, $user, $pass"); # MySQL と PDO_MYSQL $DBH = 新しい PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = new PDO("sqlite:my/database/path/database.db"); ) catch(PDOException $e) ( echo $e->getMessage(); )

ブロックに注意 トライ/キャッチ- PDO 操作は常にブロック内でラップする必要があります。 トライ/キャッチそして例外メカニズムを使用します。 通常、確立される接続は 1 つだけですが、この例では構文を示すために複数の接続を示しています。 $DBHデータベース ハンドルが含まれており、チュートリアル全体で使用されます。

ハンドルを次のように設定すると、接続を閉じることができます。 ヌル.

# 接続を閉じます $DBH = null;

さまざまなデータベースの特定のオプションと接続文字列について詳しくは、PHP.net のドキュメントを参照してください。

例外と PDO

PDO は例外を使用してエラーを処理できます。 これは、すべての PDO 操作をブロックで囲む必要があることを意味します。 トライ/キャッチ。 PDO は 3 つのレベルのエラーをスローできます。エラー制御レベルは、データベース記述子のエラー制御モード属性を設定することによって選択されます。

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

制御レベルの設定に関係なく、接続エラーは常に例外を発生させるため、常にブロックで囲む必要があります。 トライ/キャッチ.

PDO::ERRMODE_SILENT

エラー制御レベルはデフォルトで設定されています。 このレベルでは、拡張機能と同じ原理に従ってエラーが生成されます。 mysqlまたは ミスクリ。 他の 2 つのレベルのエラー制御は、DRY (Don't Reply Youself) プログラミング スタイルにより適しています。

PDO::ERRMODE_WARNING

このレベルのエラー制御では、標準の PHP 警告が生成され、プログラムは実行を続行できます。 このレベルはデバッグに便利です。

PDO::ERRMODE_EXCEPTION

ほとんどの状況では、このレベルのエラー制御を使用する必要があります。 例外は、エラーを慎重に処理し、誰かがシステムをハッキングするのに役立つ可能性のあるデータを隠すために生成されます。 以下は、例外の利点を示す例です。

# データベースに接続します try ( $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # SELECT ではなく DELECT と入力するのが間違っています! $DBH->prepare("DELECT name FROM people"); ) catch(PDOException $e) ( echo "申し訳ありませんが、操作を実行できませんでした。"; file_put_contents("PDOErrors. txt" , $e->getMessage(), FILE_APPEND); )

ここの SELECT ステートメントには意図的なエラーがあります。 これにより例外がスローされます。 例外はエラーの説明をログ ファイルに送信し、ユーザーにメッセージを表示します。

データの挿入と更新

新しいデータの挿入または既存のデータの更新は、最も一般的に使用される一般的なデータベース操作の 1 つです。 PDO を使用する場合、PDO は 2 つの段階に分解されます。 この章で説明する内容はすべて両方の操作に当てはまります。 アップデートそして 入れる.


最もよく使用されるデータ挿入タイプの例を次に示します。

# STH は「状態ハンドル」 $STH = $DBH->prepare("INSERT INTO folks (first_name)values ("Cathy")"); $STH->execute();

もちろん、この操作は次のメソッドを使用して実行できます。 実行(), 通話回数が1回減ります。 ただし、準備された式の利点を得るには、より長いメソッドを使用する方が良いでしょう。 たとえ一度だけ使用するつもりであっても、準備された式はシステムへの攻撃から保護するのに役立ちます。

準備された式

準備されたステートメントは、データのみをサーバーに送信することで何度でも実行できるプリコンパイルされた SQL ステートメントです。 SQL コード添付による攻撃に対する保護の形で、テンプレートにデータが自動的に入力されるという追加の利点もあります。

SQL コードにテンプレートを含めることで、準備された式を使用できます。 以下に 3 つの例を示します。1 つはテンプレートなし、1 つは名前のないテンプレートを使用、もう 1 つは名前付きのテンプレートを使用します。

# テンプレートがありません - SQL インジェクション攻撃にさらされます! $STH = $DBH->("人々 (名前、住所、都市) の値 ($name、$addr、$city) に挿入"); # 名前のないテンプレート $STH = $DBH->("INSERT INTO folks (name, addr, city) 値 (?, ?, ?); # 名前付きテンプレート $STH = $DBH->("INSERT INTO folks (name , addr , city) value (:name, :addr, :city)");

最初の方法は使用しないでください。 名前付きパターンまたは名前なしパターンの選択は、これらの式のデータを設定する方法に影響します。

名前のないテンプレート

# 1 ~ 3 のインデックスが付いた変数を各テンプレートに割り当てます $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $city); # 1行挿入 $name = "Dima" $addr = "Lizyukova St."; $city = "モスクワ"; $STH->execute(); # 別の行を挿入 $name = "Senya" $addr = "共産主義者の行き止まり"; $city = "ピーター"; $STH->execute();

操作は 2 段階で行われます。 最初のステップでは、変数がテンプレートに割り当てられます。 次に、変数に値が割り当てられ、式が実行されます。 次のデータを送信するには、変数の値を変更して式を再度実行する必要があります。

多くのパラメーターを含む式は少し面倒に思えますか? 確かに。 ただし、データが配列に格納されている場合、すべてが非常に短くなります。

# 挿入するデータ $data = array("Monya", "Forget-me-Not Avenue", "Zakutaysk"); $STH = $DBH->("人々 (名前、住所、都市) の値 (?, ?, ?) に挿入"); $STH->実行($data);

配列内のデータは、出現する順序でテンプレートに置き換えられます。 $data は最初のテンプレートに、$data は 2 番目のテンプレートに、というように続きます。 ただし、配列のインデックスが異なる順序で付けられている場合、そのような操作は正しく実行されません。 パターンの順序が配列内のデータの順序と一致していることを確認する必要があります。

名前付きテンプレート

名前付きテンプレートの使用例を次に示します。

# 関数の最初の引数は、名前付きテンプレートの名前です。 # 名前付きテンプレートは常にコロンで始まります $STH->bindParam(":name", $name);

ショートカットを使用することもできますが、それらは関連付けられた配列で機能します。 例:

# 挿入するデータ $data = array("name" => "Michelle", "addr" => "Kuznechny Lane", "city" => "Cnjkbwf"); # 短縮表現 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); $STH->実行($data);

テーブル キーにはコロンは必要ありませんが、テンプレート名と一致する必要があります。 配列の配列を使用している場合は、それを反復処理して単純に呼び出すことができます。 実行するデータセットごとに。

名前付きテンプレートのもう 1 つの優れた機能は、プロパティとフィールド名が一致する場合にオブジェクトをデータベースに直接挿入できることです。 例:

# 単純なオブジェクトクラス person ( public $name; public $addr; public $city; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $a; $ this->city = $c; ) # etc... ) $cathy = new person("Katya","Lenin Avenue","Mozhaisk"); # 実行: $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)"); $STH->execute((array)$cathy);

オブジェクトタイプを次のように変換します 配列 V 実行するプロパティが配列キーとして扱われるようになります。

データ受信中


データの取得には状態識別子メソッドが使用されます ->フェッチ()。 メソッドを呼び出す前に フェッチ()データベースからデータを取得する方法を PDO に指示する必要があります。 次のオプションを選択できます。

  • PDO::FETCH_ASSOC: 列名でインデックス付けされた配列を返します。
  • PDO::FETCH_BOTH (デフォルト): 列名と番号でインデックス付けされた配列を返します。
  • PDO::FETCH_BOUND: メソッドを使用して列の値を一連の変数に割り当てます。 ->バインド列()
  • PDO::FETCH_CLASS: 列の値を名前付きクラスのプロパティに割り当てます。対応するプロパティが存在しない場合は作成されます。
  • PDO::FETCH_INTO: 名前付きクラスの既存のインスタンスを更新します
  • PDO::FETCH_LAZY:組み合わせ PDO::FETCH_BOTH/PDO::FETCH_OBJ、使用時にオブジェクト変数名を作成します
  • PDO::FETCH_NUM: 列番号でインデックス付けされた配列を返します
  • PDO::FETCH_OBJ: 列名に対応するプロパティ名を持つ匿名オブジェクトを返します。

実際には、基本的な状況は次の 3 つのオプションを使用して解決されます。 FETCH_ASSOC, FETCH_CLASSそして FETCH_OBJ。 データ抽出方法を設定するには:

$STH->setFetchMode(PDO::FETCH_ASSOC);

メソッド呼び出しでデータ取得メソッドを直接設定することもできます。 ->フェッチ().

FETCH_ASSOC

このタイプのデータ取得では、列名によってインデックスが付けられた連想配列が作成されます。 拡張機能を使用している人にはかなりよく知られているはずです mysql/mysqli。 サンプルデータサンプル:

$STH = $DBH->query("人々から名前、住所、都市を選択"); # データ取得モードを設定 $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] . "\n"; )

サイクル その間完了するまで、サンプル結果を一度に 1 行ずつ反復し続けます。

FETCH_OBJ

このタイプのデータ取得では、クラス オブジェクトが作成されます 標準受信したデータの各行について:

$STH = $DBH->query("人々から名前、住所、都市を選択"); # データフェッチモードを設定 $STH->setFetchMode(PDO::FETCH_OBJ); # 結果を表示 while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \n"; )

FETCH_CLASS

このタイプの抽出では、データは選択したクラスに直接配置されます。 使用する FETCH_CLASSオブジェクトのプロパティは、コンストラクターを呼び出す前に設定されます。 それは非常に重要です。 列名に対応するプロパティが存在しない場合は、そのようなプロパティが作成されます ( 公共) あなたのために。

これは、データベースからデータを取得した後にデータの変換が必要な場合、オブジェクトが作成されるとすぐに自動的に変換できることを意味します。

たとえば、各エントリのアドレスを部分的に隠す必要がある状況を想像してください。 コンストラクターでプロパティを操作することで、このタスクを実行できます。

クラス Secret_person ( public $name; public $addr; public $city; public $other_data; function __construct($other = "") ( $this->address = preg_replace("//", "x", $this->アドレス); $this->other_data = $other; ) )

データがクラスに抽出されると、アドレス内のすべての小文字の a ~ z 文字が x 文字に置き換えられます。 ここで、クラスを使用してデータを取得すると、変換は完全に透過的に行われます。

$STH = $DBH->query("人々から名前、住所、都市を選択"); $STH->setFetchMode(PDO::FETCH_CLASS, "secret_person"); while($obj = $STH->fetch()) ( echo $obj->addr; )

住所が「Leninsky Prospekt 5」の場合は、「Lxxxxxxxxxxx xx-x 5」と表示されます。 もちろん、データが割り当てられる前にコンストラクターを呼び出したい場合もあります。 PDO にはこれを実装する手段があります。

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "secret_person");

ここで、モードを設定して前の例を繰り返すと、 PDO::FETCH_PROPS_LATEコンストラクターが呼び出され、プロパティが割り当てられているため、アドレスは非表示になりません。

必要に応じて、データをオブジェクトに抽出するときにコンストラクターに引数を渡すことができます。

$STH->setFetchMode(PDO::FETCH_CLASS, "secret_person", array("stuff"));

オブジェクトごとに異なるデータをコンストラクターに渡す必要がある場合は、メソッド内でデータ取得モードを設定できます。 フェッチ:

$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // 処理 $i++ )

その他の便利な方法

PDO を短い記事で完全に説明することはできないため、基本的な操作を実行するための便利な方法をいくつか紹介します。

$DBH->lastInsertId();

方法 ->lastInsertId()常にデータベース ハンドル (状態ハ​​ンドルではなく) によって呼び出され、指定された接続に対して最後に挿入された行の自動インクリメント ID の値を返します。

$DBH->exec("WHERE 1 の人々から削除"); $DBH->exec("SET time_zone = "-8:00"");

方法 ->exec()さまざまな補助操作に使用されます。

$safe = $DBH->quote($unsafe);

方法 ->引用()文字列をクエリで使用できるようにクォータします。 これは、準備された式が使用されない場合に備えての予備です。

$rows_affected = $STH->rowCount();

方法 ->rowCount()戻り値 整数、操作によって処理される行数を示します。 バグ レポート (http://bugs.php.net/40822) によると、PDO の最新バージョンでは、このメソッドは式では機能しません。 選択する。 問題が発生して PHP を更新できない場合は、次の方法で行数を取得できます。

$sql = "SELECT COUNT(*) FROM 人々"; if ($STH = $DBH->query($sql)) ( # 行数を確認します if ($STH->fetchColumn() > 0) ( # ここに SELECT コードがあるはずです) else ( echo "クエリに一致する行がありません。" ; ) )

レッスンが気に入って頂けたなら幸いです!

  • 翻訳

多くの PHP 開発者は、mysql および mysqli 拡張機能を使用してデータベースを操作することに慣れています。 しかし、PHP バージョン 5.1 以降では、より便利な方法、PHP データ オブジェクトが追加されました。 略して PDO と呼ばれるこのクラスは、生産性を大幅に向上させるオブジェクトとプリペアド ステートメントを操作するためのメソッドを提供します。

PDO の概要

「PDO – PHP データ オブジェクトは、複数のデータベースを操作するための普遍的な方法を提供するレイヤーです。」

これにより、さまざまな DBMS の構文機能に対する懸念は開発者に任されますが、プラットフォーム間の切り替えプロセスの負担が軽減されます。 多くの場合、これにはデータベース接続文字列の変更のみが必要です。


この記事は、mysql および mysqli を使用するユーザーを対象に、より強力で柔軟な PDO への移行を支援するために書かれています。

DBMSのサポート

この拡張機能は、PDO ドライバーが存在するあらゆるデータベース管理システムをサポートできます。 この記事の執筆時点では、次のドライバーが利用可能です。
  • PDO_CUBRID (CUBRID)
  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (ファイアバード/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix 動的サーバー)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle 呼び出しインターフェース)
  • PDO_ODBC (ODBC v3 (IBM DB2、unixODBC、および win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 および SQLite 2)
  • PDO_SQLSRV (Microsoft SQL サーバー)
  • PDO_4D (4D)
ただし、それらのすべてがサーバー上にあるわけではありません。 次のように、利用可能なドライバーのリストが表示されます。
print_r(PDO::getAvailableDrivers());

繋がり

異なる DBMS に接続する方法は若干異なる場合があります。 以下は、最も一般的なものへの接続例です。 SQLite とは異なり、最初の 3 つは同じ構文であることがわかります。
try ( # PDO_DBLIB 経由の MS SQL Server と Sybase $DBH = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass); $DBH = new PDO("sybase:host=$host) ;dbname=$dbname", $user, $pass); # PDO_MYSQL 経由の MySQL $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = new PDO("sqlite:my/database/path/database.db"); ) catch(PDOException $e) ( echo $e->getMessage(); )
try/catch ブロックに注意してください。すべての PDO 操作をこのブロックにラップし、例外メカニズムを使用することは常に価値があります (これについては後で詳しく説明します)。

$DBH は「データベース ハンドル」の略で、記事全体で使用されます。

変数を null に再定義することで、接続を閉じることができます。
# 接続を閉じます $DBH = null;
さまざまな DBMS の特有のオプションとそれらへの接続方法に関する詳細については、php.net を参照してください。

例外と PDO

PDO はエラー時に例外をスローする可能性があるため、すべてを try/catch ブロック内に含める必要があります。 接続を作成した直後、PDO は次の 3 つのエラー モードのいずれかになる可能性があります。
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
ただし、接続しようとするときにエラーが発生すると、常に例外がスローされることに注意してください。

PDO::ERRMODE_SILENT

これがデフォルトのモードです。 おそらく、mysql 拡張機能と mysqli 拡張機能のエラーを検出するために、ほぼ同じものを使用することになります。 次の 2 つのモードは、DRY プログラミングにより適しています。

PDO::ERRMODE_WARNING

このモードでは、標準の警告が発生し、スクリプトの実行が続行されます。 デバッグに便利です。

PDO::ERRMODE_EXCEPTION

ほとんどの状況では、このタイプのスクリプト実行制御が推奨されます。 例外をスローすることで、エラーを巧みに処理し、機密情報を隠すことができます。 たとえば、次のようになります。
# データベースに接続します try ( $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # くそー! SELECT の代わりに DELECT を入力してしまった! $DBH->prepare("DELECT name FROM people")->execute(); ) catch(PDOException $e) ( echo "ヒューストン、問題が発生しました。"; file_put_contents ("PDOErrors .txt", $e->getMessage(), FILE_APPEND); )
SQL 式に構文エラーがあり、例外がスローされます。 エラーの詳細をログ ファイルに記録し、人間の言語で何かが起こったことをユーザーに示唆することができます。

挿入と更新

新しいデータの挿入と既存のデータの更新は、最も一般的なデータベース操作の一部です。 PDO の場合、このプロセスは通常 2 つのステップで構成されます。 (次のセクションでは UPDATE と INSERT の両方について説明します)


新しいデータを挿入する簡単な例:
# STH は「ステートメントハンドル」を意味します $STH = $DBH->prepare("INSERT INTO folks (first_name) names ("Cathy")"); $STH->execute();
実際には、1 つの exec() メソッドでも同じことを行うことができますが、2 段階の方法ではプリペアド ステートメントのすべての利点が得られます。 これらは SQL インジェクションからの保護に役立つため、1 回限りのクエリでも使用することは理にかなっています。

準備されたステートメント

準備されたステートメントを使用すると、SQL インジェクションに対する保護が強化されます。

プリペアド ステートメントは、異なるデータ セットのみをサーバーに送信することで繰り返し実行できる、事前にコンパイルされた SQL ステートメントです。 さらに、プレースホルダーで使用されるデータを介して SQL インジェクションを実行することができないという利点もあります。

以下に、準備されたステートメントの 3 つの例を示します。
# プレースホルダーなし - SQL インジェクションへの扉は開かれています。 $STH = $DBH->prepare("INSERT INTO people (name, addr, city) 値 ($name, $addr, $city)"); # 名前のないプレースホルダー $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) names (?, ?, ?)"); # 名前付きプレースホルダー $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) 値 (:name, :addr, :city)");
最初の例は比較のみを目的としており、使用しないでください。 名前なしプレースホルダーと名前付きプレースホルダーの違いは、準備されたステートメントにデータを渡す方法です。

名前のないプレースホルダー

# 1 ~ 3 のインデックスを使用して変数を各プレースホルダーに割り当てます $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $city); # 1 行挿入 $name = "ダニエル" $addr = "1 邪悪な方法"; $city = "アーリントンハイツ"; $STH->execute(); # 別のデータを含む別の行を挿入 $name = "Steve" $addr = "5 Circle Drive"; $city = "シャンバーグ"; $STH->execute();
ここには 2 つのステップがあります。 最初の行では、変数をすべてのプレースホルダーに割り当てます (2 ~ 4 行目)。 次に、これらの変数に値を代入し、クエリを実行します。 新しいデータセットを送信するには、変数値を変更してリクエストを再度実行するだけです。

SQL 式に多数のパラメータがある場合、それぞれに変数を割り当てるのは非常に不便です。 このような場合、データを配列に保存して渡すことができます。
# 挿入するデータのセット $data = array("Cathy", "9 Dark and Twisty Road", "Cardiff"); $STH = $DBH->prepare("INSERT INTO people (name, addr, city) 値 (?, ?, ?)"); $STH->実行($data);
$data は最初のプレースホルダーの代わりに挿入され、$data は 2 番目のプレースホルダーの代わりに挿入されます。 ただし注意してください。インデックスが壊れていると、これは機能しません。

名前付きプレースホルダー

# 最初の引数はプレースホルダーの名前です # 通常はコロンで始まります # コロンなしでも機能します $STH->bindParam(":name", $name);
ここでは配列を渡すこともできますが、配列は連想的である必要があります。 ご想像のとおり、キーはプレースホルダーの名前である必要があります。
# 挿入するデータ $data = array("name" => "Cathy", "addr" => "9 Dark and Twisty", "city" => "Cardiff"); $STH = $DBH->prepare("INSERT INTO people (name, addr, city) 値 (:name, :addr, :city)"); $STH->実行($data);
名前付きプレースホルダーを使用すると便利な点の 1 つは、プロパティ名がパラメーター名と一致する場合にオブジェクトをデータベースに直接挿入できることです。 たとえば、次のようなデータを挿入できます。
# 単純なオブジェクトのクラス person ( public $name; public $addr; public $city; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $ a ; $this->city = $c; ) # など... ) $cathy = new person("Cathy","9 Dark and Twisty","Cardiff"); # ここが興味深い部分です $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) names (:name, :addr, :city)"); $STH->execute((array)$cathy);
execute() 中にオブジェクトを配列に変換すると、プロパティが配列キーとして扱われます。

データサンプリング



データは ->fetch() メソッドを使用して取得できます。 呼び出す前に、どのような形式でそれらを必要とするかを明示的に示すことをお勧めします。 いくつかのオプションがあります。
  • PDO::FETCH_ASSOC:列名をキーとして持つ配列を返します
  • PDO::FETCH_BOTH (デフォルト):列名とそのシリアル番号の両方の形式でインデックスを含む配列を返します。
  • PDO::FETCH_BOUND:->bindColumn() メソッドを使用して指定された対応する変数に列の値を割り当てます
  • PDO::FETCH_CLASS:列の値を、指定されたクラスの対応するプロパティに割り当てます。 一部の列にプロパティがない場合は作成されます
  • PDO::FETCH_INTO:指定されたクラスの既存のインスタンスを更新します
  • PDO::FETCH_LAZY: PDO::FETCH_BOTH と PDO::FETCH_OBJ を組み合わせる
  • PDO::FETCH_NUM:キーを列番号として含む配列を返します
  • PDO::FETCH_OBJ:列名に対応するプロパティを持つ匿名オブジェクトを返します。
実際には、通常、FETCH_ASSOC、FETCH_CLASS、FETCH_OBJ の 3 つが必要になります。 データ形式を指定するには、次の構文を使用します。
$STH->setFetchMode(PDO::FETCH_ASSOC);
->fetch() メソッドを呼び出すときに直接設定することもできます。

FETCH_ASSOC

この形式では、列名をインデックスとして持つ連想配列が作成されます。 mysql/mysqli 拡張機能を使用している人にはよく知られているはずです。
# これはプレースホルダーのない通常のクエリなので、 # query() メソッドをすぐに使用できます $STH = $DBH->query("SELECT name, addr, city from folks"); # フェッチモードを設定 $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] . "\n"; )
while() ループはクエリ結果全体を反復処理します。

FETCH_OBJ

このタイプのデータ取得では、行ごとに std クラスのインスタンスが作成されます。
# クエリを作成 $STH = $DBH->query("SELECT name, addr, city from folks"); # フェッチモードを選択 $STH->setFetchMode(PDO::FETCH_OBJ); # 結果を出力します while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \n"; )

FETCH_CLASS

fetch_class を使用すると、データは指定されたクラスのインスタンスに書き込まれます。 この場合、コンストラクターを呼び出す前に、オブジェクトのプロパティに値が割り当てられます。 列名に対応する名前を持つプロパティが存在しない場合は、自動的に (スコープが public で) 作成されます。

データをデータベースから受信した直後に必須の処理が必要な場合は、クラス コンストラクターで実装できます。

たとえば、人の住所の一部を隠す必要がある状況を考えてみましょう。
class Secret_person ( public $name; public $addr; public $city; public $other_data; function __construct($other = "") ( $this->addr = preg_replace("//", "x", $this-> addr); $this->other_data = $other; ) )
オブジェクトを作成するときは、すべての小文字のラテン文字を x に置き換える必要があります。 確認しよう:
$STH = $DBH->query("人々から名前、住所、都市を選択"); $STH->setFetchMode(PDO::FETCH_CLASS, "secret_person"); while($obj = $STH->fetch()) ( echo $obj->addr; )
データベース内のアドレスが「5 Rosebud」の場合、出力は「5 Rxxxxxx」になります。

もちろん、値を割り当てる前にコンストラクターを呼び出したい場合もあります。 PDO ではこれも可能です。
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "secret_person");
追加のオプション (PDO::FETCH_PROPS_LATE) で前の例を補足したので、値が書き込まれた後は何も起こらないため、アドレスは変更されません。

最後に、必要に応じて、オブジェクトの作成時にコンストラクターに引数を直接渡すことができます。
$STH->setFetchMode(PDO::FETCH_CLASS, "secret_person", array("stuff"));
各オブジェクトに異なる引数を渡すこともできます。
$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // 何かを行う $i++; )

その他の便利な方法

この記事では、PDO を使用した作業のすべての側面をカバーすることはできません (また、そのつもりもありません) (PDO は巨大なモジュールです!) が、次のいくつかの機能については言及せずに省略することはできません。
$DBH->lastInsertId();
->lastInsertId() メソッドは、最後に挿入されたレコードの ID を返します。 これは常に、式を含むオブジェクト ($STH) ではなく、データベース オブジェクト (この記事では $DBH と呼びます) に対して呼び出されることに注意してください。
$DBH->exec("WHERE 1 の人々から削除"); $DBH->exec("SET time_zone = "-8:00"");
->exec() メソッドは、影響を受けるレコード数以外のデータを返さない操作に使用されます。
$safe = $DBH->quote($unsafe);
->quote() メソッドは文字列データに引用符を配置するため、クエリで安全に使用できます。 準備されたステートメントを使用しない場合に便利です。
$rows_affected = $STH->rowCount();
->rowCount() メソッドは、操作に参加したレコードの数を返します。 残念ながら、この関数は PHP 5.1.6 までは SELECT クエリでは機能しませんでした。 PHPのバージョンを更新できない場合は、次のようにレコード数を取得できます。
$sql = "SELECT COUNT(*) FROM 人々"; if ($STH = $DBH->query($sql)) ( # レコード数を確認します if ($STH->fetchColumn() > 0) ( # データが見つかったのでここで完全選択を行います! ) else ( # リクエストを満たすデータが見つからなかったというメッセージを出力します) )

結論

この資料が、mysql および mysqli 拡張機能からの移行に役立つことを願っています。