[php]PDOの使い方(mysql接続 / 追加 / 更新 / 取得 etc)

php

phpでデータベースにアクセス時にpdoをあまり使ったことなく、mysqliをよく使っていましたが、今回PDOをゴリゴリ使うことがあったのでまとめてみました。

php7.3でコードを書いた後にターミナルから実行して確認しています。

公式ではこちらの内容になります。

phpのpdoって?

php data objectsの略で、phpからデータベースにアクセスする時に使う機能になります。
php5.1からは標準で使えるようになっているようです。

データベースアクセスしてみる

データベースを用意する

アクセスするためのデータベースを用意します。
mysqlに接続して、下記のSQLを実行してデータベースを作成します。

CREATE DATABASE test_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

character setで文字コードをutf8mb4に指定して、データベースを作成しています。

アクセスしてみる

早速mysqlデータベースにアクセスしてみます。
下記の内容をpdo_test.phpで保存して実行してみました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    }   

    echo "OK.\n";

new PDOして、mysqlにアクセスするためのインスタンスを作成します。
データベースにアクセスできない場合はここで、エラーになります。

エラーになった場合は、try catchでキャッチして、エラー内容を出力して処理を終了しています。
PDOのコンストラクタについての公式ドキュメントはこちらです。

実行してみます。

$ php pdo_test.php
OK.

接続できたので、エラーにならずに「OK.」が表示されました。

テーブルを作成する(queryでSQL実行)

pdoのqueryメソッドを使ってみます。
テーブルを作成するcreate文を実行します。

下記の内容をpdo_create_test.phpで保存して実行してみました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    }   

    $result = $database_handler->query(<<<EOF
                  CREATE TABLE products(
                    id BIGINT NOT NULL AUTO_INCREMENT,
                    name VARCHAR(255),
                    price BIGINT,
                    PRIMARY KEY (id)
                  )
              EOF);
    if($result) {
      echo  "テーブル作成に成功しました\n";
    } else {
      echo  "テーブル作成に失敗しました\n";
    }   

データベースにアクセスした後に、PDOのインスタンス(データベースハンドラ)を使って、queryメソッドを呼び出しています。
queryメソッドにproductsテーブルを作成するcreate文を入れて実行しています。

queryメソッドは成功するとPDOStatementが返ってきて、
失敗すると、falseが返ってきます。

成功した場合は成功時のメッセージ・失敗の場合は失敗メッセージを出して終了しています。

実行してみます…

$ php pdo_create_test.php 
テーブル作成に成功しました

テーブルが作成されました。
mysqlに接続して、確認するとテーブルが作成されています。

既にテーブルがあるので、2回目以降実行しても、下記のように失敗します。

$ php pdo_create_test.php 
テーブル作成に失敗しました

prepareステートメントを使ってみる

prepareステートメントを使って、データの追加・更新・削除をやってみます。

データを追加する

作ったproductsテーブルにデータを追加してみます。

こんな感じのコードを書きました。
ファイルに渡した引数でデータを登録するようにしました。

pdo_prepare_add.phpという名前で保存して実行してみました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');

        if ($statement = $database_handler->prepare("INSERT INTO products (name, price) VALUES(:name, :price)")) {
            $statement->bindParam(":name", $argv[1]);
            $statement->bindParam(":price", $argv[2]);
            $execute = $statement->execute();

            if ($execute) {
              echo "登録に成功しました。\n"; 
            } else {
              echo "登録に失敗しました。\n"; 
            }
        }
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    } 

解説

PDOオブジェクトを作った後に、prepareを呼び出して、$statement変数でPDOStatementオブジェクトを受け取ります。
受け取った変数を使って、bindParamをそれぞれ呼び出して、受け取った引数をセットします。

最後にexecuteを呼び出して、sqlを実行します。(bindParamでパラメータの箇所が埋められて実行されます)

実行する

実行してみると…

$ php pdo_prepare_add.php りんご 100
登録に成功しました。

登録されました。
登録してテーブルを確認してみると、データが入っていることが確認できます。

idnameprice
1りんご100

データを取得する

productsテーブルのデータを全て取得して表示するコードを書いてみました。
pdo_prepare_get.phpという名前で保存しました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');

        if ($statement = $database_handler->prepare("SELECT id, name, price FROM products")) {
            $statement->execute();

            $products = $statement->fetchAll(PDO::FETCH_ASSOC);
            foreach ($products as $product) {
              echo "{$product['name']}:{$product['price']}\n"; 
            }

        }
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    }   

解説

PDOオブジェクトを作った後に、prepareを呼び出して、PDOStatementオブジェクトを受け取ります。
今回はバインドするパラメータがないので(置き換えるパラメータなし)、そのままexecuteを呼び出して実行します。

executeした後に、statementオブジェクトのfetchAllメソッドを呼び出すとデータが取得できます。

fetchメソッドもあります。
fetchメソッドの方は1件のみの取得で、fetchAllは全件取得です。

実行する

実行してみると…

$ php pdo_prepare_get.php           
りんご:100
ぶどう:180
みかん:110

データが取得されて表示されました。(3件登録済み)

データを更新する

データを更新するコードを書きました。
引数として、名前・値段・更新するIDを渡すと、指定したIDの行が更新されます。

pdo_prepare_update.phpという名前で保存して、実行してみました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');

        if ($statement = $database_handler->prepare("UPDATE products set name = :name, price = :price where id = :id")) {
            $statement->bindParam(":name", $argv[1]);
            $statement->bindParam(":price", $argv[2]);
            $statement->bindParam(":id", $argv[3]);
            $execute = $statement->execute();

            if ($execute) {
              echo "更新に成功しました。\n"; 
            } else {
              echo "更新に失敗しました。\n"; 
            }
        }
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    }   

解説

実行するSQLが変わっただけで、書き方はデータ追加時と同じです。
PDOオブジェクトを作成した後にbindParamをそれぞれ呼び出して、受け取った引数をセットします。

その後executeメソッドで実行しています。

実行する

データが次の通りになっている時に

idnameprice
1りんご100
2ぶどう180
3みかん110

下記のように実行してみます。

$ php pdo_prepare_update.php ばなな 160 2
更新に成功しました。

更新されました。指定した2番目が変わりました!

idnameprice
1りんご100
2ばなな160
3みかん110

データを削除する

データを削除するコードを書きました。
pdo_prepare_delete.phpという名前で作成しました。

引数として、削除したいIDを指定します。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');

        if ($statement = $database_handler->prepare("DELETE FROM products WHERE id = :id")) {
            $statement->bindParam(":id", $argv[1]);
            $execute = $statement->execute();

            if ($execute) {
              echo "削除に成功しました。\n"; 
            } else {
              echo "削除に失敗しました。\n"; 
            }
        }
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        exit;
    }   

解説

こちらもデータ追加・更新時と同じように処理しています。
PDOオブジェクトを作成した後にパラメータをバインドして、executeで実行しています。

実行する

データが次の通りになっている時に、2番目を指定して削除してみます。

idnameprice
1りんご100
2ばなな160
3みかん110

実行すると..

$ php pdo_prepare_delete.php 2           
削除に成功しました。

削除されました!

idnameprice
1りんご100
3みかん110

トランザクション(transaction)を使ってみる

トランザクションを使った場合の処理を書いています。
pdo_transaction.phpという名前で作成しました。

<?php
    try 
    {   
        $database_handler = new PDO('mysql:host=localhost:3306;dbname=test_db;charset=utf8mb4', 'root', 'password');

        $database_handler->beginTransaction();
        if ($statement = $database_handler->prepare("INSERT INTO products (name, price) VALUES(:name, :price)")) {
            $statement->bindParam(":name", $argv[1]);
            $statement->bindParam(":price", $argv[2]);
            $execute = $statement->execute();

            if ($execute) {
              echo "登録に成功しました。\n"; 
            } else {
              echo "登録に失敗しました。\n"; 
            }

            echo "パラメータ1は{$argv[1]}\n";
            echo "パラメータ2は{$argv[2]}\n";

            if ($argv[1] == 'test') {
              throw new Exception('testは商品名としてだめ!'); 
            }
            $database_handler->commit();    
        }
    }   
    catch (PDOException $e) 
    {   
        echo "DB接続に失敗しました。\n";
        echo $e->getMessage() . "\n";
        $database_handler->rollBack();
        exit;
    }   
    catch (Exception $e) 
    {   
        echo "$e\n";    
        $database_handler->rollBack();
    }   

解説

トランザクジョンを使うとデータをテーブルに反映させるタイミングを制御できます。

commitメソッドが呼ばれるまでは、テーブルが更新されません。
エラーになって、rollBackメソッドが呼ばれるとテーブルを更新前の状態に戻してくれます、

6行目のbeginTransactionでトランザクションが開始されます。
ここからテーブルに反映された内容が、24行目のコミットで確定します。

エラーがthrowされた場合は、catchした箇所で、それぞれrollBackしています。

実行する

テーブルの状態が下記のようになっているときに

idnameprice
1りんご100
3みかん110

登録が成功するパラメータを渡します。

$ php pdo_transaction.php ぶどう 150
登録に成功しました。
パラメータ1はぶどう
パラメータ2は150

テーブルを参照すると追加されたことが確認できます。

idnameprice
1りんご100
3みかん110
4ぶどう150

商品名をtestにして、登録してみます。

$ php pdo_transaction.php test 999
登録に成功しました。
パラメータ1はtest
パラメータ2は999
Exception: testは商品名としてだめ! in /Users/hirano/pdoTest/pdo_transaction.php:22
Stack trace:
#0 {main}

22行目でexceptionがthrowされるため、rollbackされてデータが入ってないことが確認できます。

idnameprice
1りんご100
3みかん110
4ぶどう150

終わりに

長くなりましたが、簡単に今回pdoを使った操作を網羅してみました。
細かいオプションやデータの取り方もいろいろあるので、公式のドキュメントや他のサイトの情報も確認してみてください。

コメント

タイトルとURLをコピーしました