[2020/12/05] PHP PDO(PHP Data Objects)クラスを使った「AUTO_INCREMENT」カラムの取得について (No.240)
[2020/12/04] PHP PDO(PHP Data Objects)クラスを使ったトランザクションについて (No.239)
[2020/12/04] PHP PDO(PHP Data Objects)クラスを使ったデータベースへのアクセス(登録、更新、削除)について (No.238)
[2020/12/03] PHP PDO(PHP Data Objects)クラスを使ったデータベースへのアクセスについて (No.237)
[2020/12/01] PHP INIファイル(初期設定用)の読込について(parse_ini_file) (No.236)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
今回は MySQL の AUTO_INCREMENT の属性が付けられたカラムの値の取得について説明します。
AUTO_INCREMENT 属性を付けられるカラムはデータ型が整数型です。
INSERT SQLにより AUTO_INCREMENT 属性カラムを指定しない場合、順次+1された値が割り当てられます。
以下の様に、テスト用のテーブルを作成します。
「id」と「name」の2つのみのカラムを持ち、「id」に AUTO_INCREMENT を設定します。MariaDB [pdo]> CREATE TABLE `test_auto` ( -> `id` int(11) NOT NULL AUTO_INCREMENT, -> `name` varchar(100) DEFAULT NULL, -> PRIMARY KEY (id) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.91 sec) MariaDB [pdo]> show columns from `test_auto`; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(100) | YES | | NULL | | +-------+--------------+------+-----+---------+----------------+ 2 rows in set (0.05 sec) MariaDB [pdo]>
このテーブルにデータを追加してみます。
MariaDB [pdo]> INSERT INTO `test_auto` (`name`) VALUES ('test001'); Query OK, 1 row affected (0.05 sec) MariaDB [pdo]> select * from `test_auto`; +----+---------+ | id | name | +----+---------+ | 1 | test001 | +----+---------+ 1 row in set (0.00 sec)
MySQL には最後の AUTO_INCREMENT カラムの値を取得できる LAST_INSERT_ID() 関数があります。
MariaDB [pdo]> SELECT LAST_INSERT_ID() FROM `test_auto`; +------------------+ | LAST_INSERT_ID() | +------------------+ | 1 | +------------------+ 1 row in set (0.00 sec)
MySQL の LAST_INSERT_ID() 関数と同じ機能が PDO クラスの lastInsertId メソッドで行えます。
上記の「test_auto」テーブルにデータを登録し、 lastInsertId メソッドを呼出してみます。<?php /* [pdo17.php] */ ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // レコード登録(INSERT)SQL:[id]は AUTO_INCREMENT なので指定しない $sql = "insert into `test_auto` (name) VALUE (:name)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行 $ret = $pdostmt->execute(array(":name" => 'test002')); // [test_auto.id]の取得 $id = $pdo->lastInsertId(); echo "lastInsertId() = $id \n"; // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。2件目のレコードが追加されたので「id」に「2」が返されるのがわかります。
C:\xampp\htdocs\_test>php pdo17.php lastInsertId() = 2
テーブルの中身を見てみます。
MariaDB [pdo]> select * from `test_auto`; +----+---------+ | id | name | +----+---------+ | 1 | test001 | | 2 | test002 | +----+---------+ 2 rows in set (0.05 sec) MariaDB [pdo]>
この lastInsertId メソッドは、登録した直後のデータの「id」を取得しますが、これの必要な場面とは何があるのでしょうか。
例えば、売上データで、売上ヘッダテーブルと売上明細テーブルを分けて持つ場合です。
売上ヘッダデータと売上明細データは 1:N の関係で、同じ「id」で紐づけられると思います。
最初に売上ヘッダデータを登録し、その直後に lastInsertId メソッドで「id」を取得し、 売上明細にはその「id」と明細の連番で売上明細テーブルに登録するといった手順になると思います。
■トランザクション処理の中の AUTO_INCREMENT について
トランザクション処理の中で1件データを追加し、その後で明示的にエラーが発生するSQL文を実行し、ロールバックを行わせてみます。 以下にそのスクリプトを示します。
<?php /* [pdo18.php] */ ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // トランザクション開始 $ret = $pdo->beginTransaction(); if ($ret == true) { // トランザクション開始OK try { // レコード登録(INSERT)SQL:[id]は AUTO_INCREMENT なので指定しない $sql = "insert into `test_auto` (name) VALUE (:name)"; $pdostmt = $pdo->prepare($sql); $ret = $pdostmt->execute(array(":name" => 'test003')); // [test_auto.id]の取得 $id = $pdo->lastInsertId(); echo "lastInsertId() = $id \n"; // エラーの発生するレコード登録(INSERT)SQL $sql = "insert into `test_auto` (name) VALUE ()"; $pdostmt = $pdo->prepare($sql); $ret = $pdostmt->execute(); // この時点でエラー発生 } catch (Exception $e) { // 何かスクリプト上のエラーが在った!! $ret = false; } // トランザクション終了処理 if ($ret == true) { // コミット $pdo->commit(); echo "commit() \n"; } else { // ロールバック $pdo->rollback(); echo "rollback() \n"; } // [test_auto.id]の取得 $id = $pdo->lastInsertId(); echo "lastInsertId() = $id \n"; } else { // トランザクション開始NG } // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。 登録実行後、最初の lastInsertId メソッドでは「3」が返されますが、 次の INSERT 処理ではエラーが発生し、ロールバック処理が行われます。 この後で、 lastInsertId メソッドを実行してもトランザクション開始前の状態に戻るため、「0」が返ります。
C:\xampp\htdocs\_test>php pdo18.php lastInsertId() = 3 rollback() lastInsertId() = 0
この状態で、テーブルの属性を SHOW TABLE コマンドで見てみます。MariaDB [pdo]> SHOW TABLE STATUS LIKE 'test_auto'\G *************************** 1. row *************************** Name: test_auto Engine: InnoDB Version: 10 Row_format: Compact Rows: 3 Avg_row_length: 5461 Data_length: 16384 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: 4 Create_time: 2020-12-04 18:39:53 Update_time: NULL Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: Comment: 1 row in set (0.00 sec)
test_auto の Auto_increment は「4」となり、次の追加処理が行われた時にはその値「4」が設定されます。
トランザクション中に Auto_increment の変化が在ったのですがロールバックしても値は「4」のままとなります。
上記のソースでは「3」の値でINSERTしたのですが、その後のエラーSQLでロールバックされ「3」は欠番となります。
この結果は少し、不都合な感じもしますが、複数のマシンから同じスクリプトが起動され、 それぞれが別々の Auto_increment の値を取る様にするためには必要なことだと思います。
PR -
PDO を使ったデータベースへの接続とテーブルレコード取得、及びデータレコードに対しての登録(INSERT)、更新(UPDATE)、削除(DELETE)について、以下の記事で説明しました。
⇒PHP PDO(PHP Data Objects)クラスを使ったデータベースへのアクセスについて
⇒PHP PDO(PHP Data Objects)クラスを使ったデータベースへのアクセス(登録、更新、削除)について
そこで、今回はデータ処理に関連して重要な方法であるトランザクション処理について説明します。
トランザクション処理 とは複数実行されるデータの登録(INSERT)、更新(UPDATE)、削除(DELETE)処理を一時的に蓄えておいて、 全ての処理が正常であれば、一括でデータベースに反映させるものです。
尚、どれかの処理でエラーが発生した場合には、全ての処理を取止め、データベースの状態をトランザクション開始の前の状態に戻せます。
トランザクション処理 を行うには以下の PDO クラスのメソッドを使います。- PDO::beginTransaction — トランザクションを開始する
- PDO::commit — トランザクションをコミットする(データベースへの一括反映)
- PDO::rollBack — トランザクションをロールバックする(トランザクション開始以降の処理を廃棄)
これらのメソッドは 返り値 として成功した場合に TRUE を、失敗した場合に FALSE を返します。
トランザクション処理 の実装としては以下の様に行います。(実際の処理では無く日本語で記述しています)// データベースへの接続 $pdo = new PDO( ... ); // トランザクション開始 $ret = $pdo->beginTransaction(); if ($ret == true) { // トランザクション開始が正常の場合 // 複数のデータの登録(INSERT)、更新(UPDATE)、削除(DELETE)の処理 ... if (データ処理が正常チェック) { // 正常の場合 $ret = $pdo->commit(); // コミット処理 } else { // エラーの場合 $ret = $pdo->rollBack(); // ロールバック処理 } } else { // トランザクション開始がエラーの場合 // (必要であれば処理記述) } // 接続を閉じる $pdo = null;
■トランザクション・コミットの例
トランザクション・コミットの例として、最初のテーブルデータを全て削除(DELETE)後、2件のデータを追加(INSERT)します。 最後にコミットを行い、テーブルの全データの一覧を表示します。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // === 全データの取得・表示 === function dispAll($_pdo) { $sql = "select * from `tm_shohin` order by id"; // 全データ取得SQL $pdostmt = $_pdo->prepare($sql); // SELECTクエリの準備 $pdostmt->execute(); // SELECTクエリの実行 while ($result = $pdostmt->fetch()) { echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "\n"; } // トランザクション開始 $ret = $pdo->beginTransaction(); // 全レコード削除(UPDATE)SQL $sql = "delete from `tm_shohin`"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行 $ret = $pdostmt->execute(); // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行([id:1]のデータ) $ret = $pdostmt->execute(array(":id" => 1, ":name" => 'パソコン001', ":price" => 100000)); // SQL文の実行([id:2]のデータ) $ret = $pdostmt->execute(array(":id" => 2, ":name" => 'パソコン002', ":price" => 202000)); // コミット $ret = $pdo->commit(); // 処理後の表示 dispAll($pdo); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。2件のレコードが追加されたのがわかります。
C:\xampp\htdocs\_test>php pdo12.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000
■トランザクション・ロールバックの例
トランザクション・ロールバックの例として、2件のデータを追加(INSERT)し, 最後にロールバックを行い、テーブルの全データの一覧を表示します。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // === 全データの取得・表示 === function dispAll($_pdo) { $sql = "select * from `tm_shohin` order by id"; // 全データ取得SQL $pdostmt = $_pdo->prepare($sql); // SELECTクエリの準備 $pdostmt->execute(); // SELECTクエリの実行 while ($result = $pdostmt->fetch()) { echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "\n"; } // 処理前の表示 dispAll($pdo); // トランザクション開始 $ret = $pdo->beginTransaction(); // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行([id:3]のデータ) $ret = $pdostmt->execute(array(":id" => 3, ":name" => 'パソコン003', ":price" => 303000)); // SQL文の実行([id:4]のデータ) $ret = $pdostmt->execute(array(":id" => 4, ":name" => 'プリンタ001', ":price" => 50000)); // ロールバック $ret = $pdo->rollback(); // 処理後の表示 dispAll($pdo); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。INSERT 処理されたデータが登録されていないことがわかります。
C:\xampp\htdocs\_test>php pdo13.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000
■トランザクション・コミットせずにスクリプトが終了した場合
上記のスクリプトからロールバックの部分を忘れた状況にしてみます。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // トランザクション開始 $ret = $pdo->beginTransaction(); // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行([id:3]のデータ) $ret = $pdostmt->execute(array(":id" => 3, ":name" => 'パソコン003', ":price" => 303000)); // SQL文の実行([id:4]のデータ) $ret = $pdostmt->execute(array(":id" => 4, ":name" => 'プリンタ001', ":price" => 50000)); // 接続を閉じる //$pdo = null; ?>
これを実行し、MySQLから直接一覧を取ると以下の様に表示されます。INSERT 処理されたデータが登録されていないことがわかります。
MariaDB [pdo]> select * from tm_shohin; +----+-------------+--------+ | id | name | price | +----+-------------+--------+ | 1 | パソコン001 | 100000 | | 2 | パソコン002 | 202000 | +----+-------------+--------+ 2 rows in set (0.00 sec)
これはトランザクションが開始され途中でコミットをせずにスクリプトが終わるとロールバックされるからです。
尚、接続を閉じるための PDO オブジェクトの null 設定を省いていますが、 PDO オブジェクトもスクリプトが終了する時には廃棄されるのと同時に、接続は閉じられます。
■トランザクション・一般的な例
トランザクション処理を行うデータ更新処理の一般的な例としては、以下の様な処理になるかと思います。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // トランザクション開始 $ret = $pdo->beginTransaction(); if ($ret == true) { // トランザクション開始OK try { // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行([id:3]のデータ) if ($ret == true) { $ret = $pdostmt->execute(array(":id" => 3, ":name" => 'パソコン003', ":price" => 303000)); } // SQL文の実行([id:4]のデータ) if ($ret == true) { $ret = $pdostmt->execute(array(":id" => 4, ":name" => 'プリンタ001', ":price" => 50000)); } // その他処理があれば続く... } catch (Exception $e) { // 何かスクリプト上のエラーが在った!! $ret = false; } // トランザクション終了処理 if ($ret == true) { // コミット $pdo->commit(); } else { // ロールバック $pdo->rollback(); } } else { // トランザクション開始NG } // 接続を閉じる $pdo = null; ?>
-
PDO を使ったデータベースへの接続と、テーブルレコード取得を以下の記事で説明しました。
⇒PHP PDO(PHP Data Objects)クラスを使ったデータベースへのアクセスについて
そこで、今回はデータレコードに対しての登録(INSERT)、更新(UPDATE)、削除(DELETE)について説明します。■テーブルレコード登録(INSERT)の例
テーブルにレコード登録を行う場合 prepare メソッドでSQL文を作成し execute メソッドでSQL文を実行します。
今回のSQL文には バインドパラメータ が無いので prepare メソッドは引数無しで実行します。
尚、レコード登録の前後で全データの一覧を表示する関数「dispAll」を宣言しました。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // === 全データの取得・表示 === function dispAll($_pdo) { $sql = "select * from `tm_shohin` order by id"; // 全データ取得SQL $pdostmt = $_pdo->prepare($sql); // SELECTクエリの準備 $pdostmt->execute(); // SELECTクエリの実行 while ($result = $pdostmt->fetch()) { echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "\n"; } // 登録前の表示 dispAll($pdo); // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (6, 'プリンタ003', 60000)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行 $pdostmt->execute(); // パラメータが無いので指定しない // 登録後の表示 dispAll($pdo); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。「id = 6」のレコードが追加されたのがわかります。
C:\xampp\htdocs\_test>php pdo6.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:6 name :プリンタ003 price:60000
「id = 6」のレコードが存在している状況で、再度レコード登録を行うと、どうなるのでしょうか。
以下のスクリプトを実行してみます。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (6, 'プリンタ003', 60000)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行 $ret = $pdostmt->execute(); // 返り値を変数で受ける var_dump($ret); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に返り値が false で返されるのが分かります。
上記の登録が正常な場合には true が返されているはずです。 実際の処理においては、返り値で登録が正常または異常かを判断して、その後の処理を行う必要があります。C:\xampp\htdocs\_test>php pdo7.php bool(false)
上のスクリプトは固定のSQL文でしたが、以下に 名前付パラメータ を含むものしたスクリプトを記します。
1回の prepare で複数のデータ実行ができることが分かります。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // SQL文の実行(名前付パラメータのデータを配列で指定) $ret = $pdostmt->execute(array(":id" => 7, ":name" => 'マウス001', ":price" => 3000)); // 準備済みのSQLを利用して別のデータで実行 $ret = $pdostmt->execute(array(":id" => 8, ":name" => 'マウス002', ":price" => 5000)); // 接続を閉じる $pdo = null; ?>
execute メソッドの引数に配列で設定するのではなく、以下の bindValue メソッドを使って各名前付パラメータに値を設定できます。
// bindValueメソッド定義 public PDOStatement::bindValue ( mixed $parameter , mixed $value [, int $data_type = PDO::PARAM_STR ] ) : bool $parameter パラメータ ID。 名前付パラメータを使用するプリペアドステートメントの場合は、:name 形式のパラメータ名となります。 疑問符パラメータを使用するプリペアドステートメントの場合は、1 から始まるパラメータの位置となります。 実行される SQL 文の中のバインドパラメータと同数の要素からなる、値の配列。 $value パラメータにバインドする値。 $data_type パラメータに対して PDO::PARAM_* 定数 を使った明示的なデータ型を指定します。 返り値: 成功した場合に TRUE を、失敗した場合に FALSE を返します。
bindValue メソッドを使ってデータ登録を行うスクリプトを記します。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // レコード登録(INSERT)SQL $sql = "insert into `tm_shohin` (id, name, price) VALUE (:id, :name, :price)"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // データ変数設定 $intId = 9; $strName = "マウス003"; $intPrice = 7000; // データバインド $pdostmt->bindValue(":id" , $intId , PDO::PARAM_INT); $pdostmt->bindValue(":name" , $strName , PDO::PARAM_STR); $pdostmt->bindValue(":price", $intPrice, PDO::PARAM_INT); // SQL文の実行 $ret = $pdostmt->execute(); // 接続を閉じる $pdo = null; ?>
■テーブルレコード更新(UPDATE)の例
レコートの登録(追加)が一通り終わりましたので、更新に付いて記します。
更新の場合も、登録と同様にSQL文を prepare メソッドで準備し bindValue メソッドを使って名前付パラメータに値を設定後、 execute メソッドでSQLの実行を行います。
以下の更新処理は、「id」が「1」~「3」の「price」を1.1倍にします。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // === 全データの取得・表示 === function dispAll($_pdo) { $sql = "select * from `tm_shohin` order by id"; // 全データ取得SQL $pdostmt = $_pdo->prepare($sql); // SELECTクエリの準備 $pdostmt->execute(); // SELECTクエリの実行 while ($result = $pdostmt->fetch()) { echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "\n"; } // 更新前の表示 dispAll($pdo); // レコード更新(UPDATE)SQL $sql = "update `tm_shohin` set price = price * 1.1 where id >= :id1 and id <= :id2"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // データ変数設定 $intId1 = 1; $intId2 = 3; // データバインド $pdostmt->bindValue(":id1", $intId1, PDO::PARAM_INT); $pdostmt->bindValue(":id2", $intId2, PDO::PARAM_INT); // SQL文の実行 $ret = $pdostmt->execute(); // 更新後の表示 dispAll($pdo); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。「id」が「1」~「3」の「price」が1.1倍になったのがわかります。
C:\xampp\htdocs\_test>php pdo10.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:6 name :プリンタ003 price:60000 id:7 name :マウス001 price:3000 id:8 name :マウス002 price:5000 id:9 name :マウス003 price:7000 id:1 name :パソコン001 price:110000 id:2 name :パソコン002 price:222200 id:3 name :パソコン003 price:333300 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:6 name :プリンタ003 price:60000 id:7 name :マウス001 price:3000 id:8 name :マウス002 price:5000 id:9 name :マウス003 price:7000
■テーブルレコード削除(DELETE)の例
prepare メソッドで削除SQLを準備し bindValue メソッドを使って名前付パラメータに値を設定後、 execute メソッドで削除の実行を行います。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // === 全データの取得・表示 === function dispAll($_pdo) { $sql = "select * from `tm_shohin` order by id"; // 全データ取得SQL $pdostmt = $_pdo->prepare($sql); // SELECTクエリの準備 $pdostmt->execute(); // SELECTクエリの実行 while ($result = $pdostmt->fetch()) { echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "\n"; } // 削除前の表示 dispAll($pdo); // レコード削除(UPDATE)SQL $sql = "delete from `tm_shohin` where id between :id1 and :id2"; // SQL文の準備 $pdostmt = $pdo->prepare($sql); // データ変数設定 $intId1 = 7; $intId2 = 9; // データバインド $pdostmt->bindValue(":id1", $intId1, PDO::PARAM_INT); $pdostmt->bindValue(":id2", $intId2, PDO::PARAM_INT); // SQL文の実行 $ret = $pdostmt->execute(); // 削除後の表示 dispAll($pdo); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。「id 」の「7」~「9」のレコードが削除されたのがわかります。
C:\xampp\htdocs\_test>php pdo11.php id:1 name :パソコン001 price:110000 id:2 name :パソコン002 price:222200 id:3 name :パソコン003 price:333300 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:6 name :プリンタ003 price:60000 id:7 name :マウス001 price:3000 id:8 name :マウス002 price:5000 id:9 name :マウス003 price:7000 id:1 name :パソコン001 price:110000 id:2 name :パソコン002 price:222200 id:3 name :パソコン003 price:333300 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 id:6 name :プリンタ003 price:60000
-
PDO とは PHP Data Objects の略称で、アクセス先のデータベースの種類を意識することなく、アクセスできるようにしたクラスです。
今まではMySQLへ接続する場合は「mysql_connect」関数を使用し、PostgreSQLの場合は「pg_connect」関数で行っていました。 また、SQL実行などもそれぞれの関数を使用しなければなりませんので、データベースごとに異なるクラスを使用する必要があります。
しかし、PDO であればデータベースの違いを吸収してくれますので、同じソースで各データベースにアクセスできます。 (厳密な意味においては、データベース毎の特殊な処理とか、SQLの違いはありますが。)
この記事では、データベースへの接続とテーブルレコード取得を説明します。
テーブルに対しての登録(INSERT)、更新(UPDATE)、削除(DELETE)については、別の記事で説明します。- データベースへの接続
- テーブルレコード取得(SELECT : query)の例
- テーブルレコード取得(SELECT : query)の複数取得の例
- テーブルレコード取得(SELECT : prepare, excute)の例
■データベースへの接続
そこで、先ずは mysql データベースへの接続に付いて説明します。
PDOクラスでは、インスタンス生成を行うと同時に接続を行います。
PDOクラスのコンストラクタ(クラス生成時の関数)は以下の様な宣言になっています。public PDO::__construct ( string $dsn [, string $username [, string $passwd [, array $options ]]] ) $dsn データソース名(Data Source Name)で、データベースに接続するために 必要な情報が含まれます。 $username ユーザ名 $passwd パスワード $options ドライバ固有の接続オプションを指定する配列 返り値: 接続成功時に PDO オブジェクトを返します。 エラー: データベースへの接続に失敗した場合 PDOException を投げます。
尚、データソース名(DSN)の指定は以下の様になります。// DSN指定文字列 mysql:host=hostname;port=portno;dbname=databasename hostname データベースサーバが存在するホスト名 portno データベースサーバーが待機しているポートNO databasename データベース名
実際にデータベースへの接続を行うソースを見て下さい。 ホストは xampp と共にインストールした MySQL への接続を行っています。
尚、 Windowsコマンドプロンプトで実行するため echo 出力が文字化けしない様に、先頭でコンソール出力への文字コード変換用に 関数を定義しています。
最後の行で、接続を閉じるために PDO オブジェクト変数に null を設定しています。 この処理によって明示的にデータベースへの接続を閉じることが出来ます。 この処理が無くても、スクリプトの終了時にデータベースへの接続を閉じられますが、書いた方が無難かと思います。<?php // Windowsコマンドプロンプトで実行するために、コンソール出力を UTF-8 ⇒ Shift-JIS 変換 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); echo "データベース接続OK\n"; } catch (PDOException $e) { // エラー発生 echo 'データベース接続ERROR:'.$e->getMessage()."\n"; exit(); } // データベースへの処理... // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。
C:\xampp\htdocs\_test>php pdo1.php データベース接続OK
MySQL は起動されていて pdo と名付けられたデータベースは存在するので、接続OKと表示されます。
そこで エラーを発生させるためにデータベース名を間違ったものにしてみます。 5行目の「pdo」 を 「pdo1」 にして上記のソースを実行します。C:\xampp\htdocs\_test>php pdo1.php データベース接続ERROR:SQLSTATE[HY000] [1049] Unknown database 'pdo1'
さらにパスワードを間違ったものにしてみます。 7行目の 'password' の中身を 'passwordx' にして上記のソースを実行します。
C:\xampp\htdocs\_test>php pdo1.php データベース接続ERROR:SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)
■テーブルレコード取得(SELECT : query)の例
まず最初に pdo データベースにテスト用のテーブルを作成します。 テーブルは商品マスタ的なものとし 「ID」「名称」「単価」のカラムを持つ簡単なものにします。
データベースを生成し、商品マスタ(tm_shohin)テーブルを生成後、数件のデータを登録しています。 これらの処理をコマンドプロンプトから mysql を起動し実行した結果が以下の様になります。MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS `pdo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; Query OK, 1 row affected (0.03 sec) MariaDB [(none)]> use pdo Database changed MariaDB [pdo]> CREATE TABLE `tm_shohin` ( -> `id` bigint(20) NOT NULL, -> `name` varchar(100) DEFAULT NULL, -> `price` bigint(20) DEFAULT NULL -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.50 sec) MariaDB [pdo]> ALTER TABLE `tm_shohin` -> ADD PRIMARY KEY (`id`); Query OK, 0 rows affected (1.34 sec) Records: 0 Duplicates: 0 Warnings: 0 MariaDB [pdo]> desc tm_shohin; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | id | bigint(20) | NO | PRI | NULL | | | name | varchar(100) | YES | | NULL | | | price | bigint(20) | YES | | NULL | | +-------+--------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) MariaDB [pdo]> set names cp932; Query OK, 0 rows affected (0.00 sec) MariaDB [pdo]> INSERT INTO `tm_shohin` (`id`, `name`, `price`) VALUES -> (1, 'パソコン001', 100000), -> (2, 'パソコン002', 202000), -> (3, 'パソコン003', 303000), -> (4, 'プリンタ001', 50000), -> (5, 'プリンタ002', 150000); Query OK, 5 rows affected (0.08 sec) Records: 5 Duplicates: 0 Warnings: 0 MariaDB [pdo]> select * from tm_shohin; +----+-------------+--------+ | id | name | price | +----+-------------+--------+ | 1 | パソコン001 | 100000 | | 2 | パソコン002 | 202000 | | 3 | パソコン003 | 303000 | | 4 | プリンタ001 | 50000 | | 5 | プリンタ002 | 150000 | +----+-------------+--------+ 5 rows in set (0.00 sec)
準備は整いましたので、PDOオブジェクトの queryメソッドを使ってデータを取得してみます。 (queryメソッドの説明は本家のマニュアルから以下となります)
// queryメソッド定義 public PDO::query ( string $statement ) : PDOStatement $statement 準備、発行する SQL ステートメント。 返り値: PDOStatement オブジェクトを返します。 失敗した場合は FALSE を返します。 PDO::query() は、一回の関数コールの中で SQL ステートメントを実行し、このステートメントにより返された 結果セット (ある場合) を PDOStatement オブジェクトとして返します。 複数回発行する必要があるステートメントの場合、 PDO::prepare() で PDOStatement ステートメントを準備し、 PDOStatement::execute() でそのステートメントを 複数回発行する方がより良いパフォーマンスを得られると実感するでしょう。 PDO::query() を次にコールする前に 結果セット内の全てのデータを取得しない場合、そのコールは失敗します。 PDOStatement::closeCursor() をコールし、 次に PDO::query() をコールする前に PDOStatement オブジェクトに関連付けられたリソースを解放してください。
この query メソッドにSQL文を渡し、返される PDOStatement オブジェクトの fetch メソッドでデータ取得を行います。 (queryメソッドの説明は本家のマニュアルから以下となります)// fetchメソッド定義 public PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] ) : mixed $fetch_style レコードを呼び出し元に返す方法を制御します。 PDO::FETCH_* 定数のどれかで、デフォルトは PDO::FETCH_BOTH です。 $cursor_orientation スクロール可能なカーソルを表す PDOStatement オブジェクトの場合、 この値により呼び出し側に返される行を定義します。 $cursor_offset スクロール可能なカーソルを表すPDOStatementオブジェクトの場合で、 cursor_orientationパラメータが PDO::FETCH_ORI_ABSに設定された場合、 この値により 取得される結果セットの行の絶対位置が指定されます。 返り値: この関数が成功した場合の返り値は、取得形式によって異なります。 失敗した場合は常に FALSE を返します。
queryメソッドは第1引数しか使ったことが無く、通常でしたら引数無しでも十分です。 それでは、商品マスタから「id = 1」の行を取得し表示するソースを以下に示します。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // データ取得SQL(結果が1行しか返さない) $sql = "select * from `tm_shohin` where id = 1"; // SELECTクエリの実行 $pdostmt = $pdo->query($sql); // PDOStatementクラスの fetch メソッドで1行のデータ取得 $result = $pdostmt->fetch(); // データ表示 echo "id :".$result["id"]."\n"; echo "name :".$result["name"]."\n"; echo "price:".$result["price"]."\n"; // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。
C:\xampp\htdocs\_test>php pdo2.php id :1 name :パソコン001 price:100000
変数 $result を print_r で見てみると以下の様になります。 カラム名とカラム位置のキーでデータの配列が設定されていることが分かります。
Array ( [id] => 1 [0] => 1 [name] => パソコン001 [1] => パソコン001 [price] => 100000 [2] => 100000 )
■テーブルレコード取得(SELECT : query)の複数取得の例
上記のスクリプトでは1件のデータのみの取得を行いましたが、1回目の fetch 処理の後、再度 fetch を行うとどうなるでしょうか?
では以下のスクリプトを実行してみます。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // データ取得SQL(結果が1行しか返さない) $sql = "select * from `tm_shohin` where id = 1"; // SELECTクエリの実行 $pdostmt = $pdo->query($sql); // PDOStatementクラスの fetch メソッドで1行のデータ取得 $result = $pdostmt->fetch(); // データ内容表示 var_dump($result); // 再度の fetch メソッド実行 $result = $pdostmt->fetch(); // データ内容表示 var_dump($result); // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。
array(6) { ["id"]=> string(1) "1" [0]=> string(1) "1" ["name"]=> string(15) "パソコン001" [1]=> string(15) "パソコン001" ["price"]=> string(6) "100000" [2]=> string(6) "100000" } bool(false)
1回目の fetch 処理後は変数 $result には配列データが返っていますが、 2回目の fetch 処理後は false が返っています。 これは、2回目の fetch でエラーが発生したことを示しています。
指定されたSQL文は1件のデータしか返さないので、2回目の取得ではエラーが発生するのは当然です。
もし複数のデータを返すSQL文で、連続して fetch 処理を行う場合に $result の内容が false であれば、 データの最後まで来て終わったことを示します。 では、複数データを返す例を以下のスクリプトで示します。<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // データ取得SQL(全てのデータを「id」昇順に取得) $sql = "select * from `tm_shohin` order by id"; // SELECTクエリの実行 $pdostmt = $pdo->query($sql); // PDOStatementクラスの fetch メソッドで1行のデータ取得 while ($result = $pdostmt->fetch()) { // データの取得と終りの判定を同時に行う!! // データが取得できた場合(データ表示) echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "end...\n"; // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。
C:\xampp\htdocs\_test>php pdo4.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 id:4 name :プリンタ001 price:50000 id:5 name :プリンタ002 price:150000 end...
■テーブルレコード取得(SELECT : prepare, excute)の例
データ取得の方法は query メソッドを使用する他に、 prepare, excute メソッドを使用する方法があります。
// prepareメソッド定義 public PDO::prepare ( string $statement [, array $driver_options = array() ] ) : PDOStatement $statement 有効な SQL 文のテンプレート $driver_options この配列はこのメソッドによって返される PDOStatement オブジェクトに対して 1 もしくはそれ以上の key=>value の組を含みます。 返り値: データベースサーバーが正常に文を準備する場合、PDO::prepare() は PDOStatement オブジェクトを返します。 もしデータベースサーバーが文を準備できなかった場合、 PDO::prepare() は FALSE を返すか PDOException を発行します (エラー処理 の方法に依存します)。
このメソッドで指定するSQL文のテンプレートは、後から指定される値で置き換えされるパラメータ識別子を含むものになります。 以下にその例を記します。
// 名前付きパラメータを用いて SQL ステートメントのテンプレート select * from `tm_shohin` where id >= :id1 and id <= :id2; // 疑問符パラメータを用いて SQL ステートメントのテンプレート select * from `tm_shohin` where id >= ? and id <= ?;
名前付きパラメータのSQLは「:id1」「:id2」がパラメータで、疑問符パラメータのSQLは2個の「?」マークがパラメータです。
尚、このSQL文を prepare メソッドで実行し、返された PDOStatement オブジェクトの excute メソッドでパラメータを指定し、 SQLの実行を行います。// executeメソッド定義 public PDOStatement::execute ([ array $input_parameters = NULL ] ) : bool $input_parameters 実行される SQL 文の中のバインドパラメータと同数の要素からなる、値の配列。 すべての値は PDO::PARAM_STR として扱われます。 ひとつのパラメータに対して複数の値をバインドすることはできません。 例えば、IN() 句の中のひとつのパラメータに対して 2 つの値をバインドすることはできません。 返り値: 成功した場合に TRUE を、失敗した場合に FALSE を返します。
それでは、名前付きパラメータと疑問符パラメータを用いた場合のスクリプトを以下に記します。
<?php ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // MySQLデータベースに接続 $dsn = "mysql:host=localhost;dbname=pdo;"; $user = 'root'; $password = 'password'; try { // PDOクラス生成(データベース接続) $pdo = new PDO($dsn, $user, $password); } catch (PDOException $e) { // エラー発生 die('データベース接続ERROR:'.$e->getMessage()."\n"); } // データ取得SQL(名前付きパラメータ) $sql = "select * from `tm_shohin` where id >= :id1 and id <= :id2 order by id"; // SELECTクエリのprepare $pdostmt = $pdo->prepare($sql); // SELECTクエリのパラメータに実際の値設定 $pdostmt->execute(array(":id1" => "1", ":id2" => "3")); // PDOStatementクラスの fetch メソッドで1行のデータ取得 while ($result = $pdostmt->fetch()) { // データが取得できた場合(データ表示) echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "end...1\n"; // データ取得SQL(疑問符パラメータ) $sql = "select * from `tm_shohin` where id >= ? and id <= ? order by id"; // SELECTクエリのprepare $pdostmt = $pdo->prepare($sql); // SELECTクエリのパラメータに実際の値設定 $pdostmt->execute(array(0 => "1", 1 => "4")); // array("1", "4") でもOK // PDOStatementクラスの fetch メソッドで1行のデータ取得 while ($result = $pdostmt->fetch()) { // データが取得できた場合(データ表示) echo "id:".$result["id"]." name :".$result["name"]." price:".$result["price"]."\n"; } echo "end...2\n"; // 接続を閉じる $pdo = null; ?>
これを実行すると以下の様に表示されます。
C:\xampp\htdocs\_test>php pdo5.php id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 end...1 id:1 name :パソコン001 price:100000 id:2 name :パソコン002 price:202000 id:3 name :パソコン003 price:303000 id:4 name :プリンタ001 price:50000 end...2
よほどのことが無ければ「疑問符パラメータ」は使用しないと思います。「名前付きパラメータ」の方が分かりやすいと思います。
-
PHP においても Windows の様にINIファイルを読込んで設定値として利用できる関数があります。
それが parse_ini_file で関数の引数にINIファイルのファイル名を指定すれば、INIファイルの中身を全て配列として返してきます。 Windows のINIファイル用の API と較べれば非常に簡単です。
■parse_ini_file の使用例
関数定義は以下の通りです。
// 関数定義 array parse_ini_file ( string $filename [, bool $process_sections = false [, int $scanner_mode = INI_SCANNER_NORMAL ]] ) [引数] $filename ini ファイル指定 $process_sections TRUE を設定するとセクション名と設定が含まれた多次元の配列を得ることができます $scanner_mode INI_SCANNER_NORMAL (デフォルト) または INI_SCANNER_RAW を指定すると、 オプションの値はパースされません。 PHP 5.6.1 以降では INI_SCANNER_TYPED も指定でき、 boolean や null そして integer の型を、可能な限り維持します [返り値] 成功した場合に設定を連想配列形式で返します。 失敗した場合に FALSE を返します。
それでは以下のINIファイルを読込んでみます。
; これはテストINIファイルです。[test.ini] [section1] data1 = 1 data2 = 1000 data3 = abcde [section2] string1 = "aaa123" string2 = "bbbbb11" [section3] array1[] = "100" array1[] = "200" array1[] = "300" array2["test1"] = "test1aaa" array2["test2"] = "test2bbbbb"
以下にセクションを意識する指定と、そうでない指定で行ってみます。<?php // $process_sections 未指定 $arr = parse_ini_file("test.ini"); print_r($arr); // $process_sections 指定 $arr = parse_ini_file("test.ini", true); print_r($arr); ?>
実行結果は以下の様に表示されます。
Array ( [data1] => 1 [data2] => 1000 [data3] => abcde [string1] => aaa123 [string2] => bbbbb11 [array1] => Array ( [0] => 100 [1] => 200 [2] => 300 ) [array2] => Array ( [test1] => test1aaa [test2] => test2bbbbb ) ) Array ( [section1] => Array ( [data1] => 1 [data2] => 1000 [data3] => abcde ) [section2] => Array ( [string1] => aaa123 [string2] => bbbbb11 ) [section3] => Array ( [array1] => Array ( [0] => 100 [1] => 200 [2] => 300 ) [array2] => Array ( [test1] => test1aaa [test2] => test2bbbbb ) ) )
セクションを指定すると、セクション毎に配列となり、セクション以下は更にその中の配列になっています。
■parse_ini_file の使用例その2
私のPHPは PHP Version 5.6.28 ですので、第3引数を INI_SCANNER_TYPED の指定を行い実行してみます。
内部的に文字列なのか、数値なのかが分かりにくいので出力は var_dump を使います。<?php // $process_sections 指定 $arr = parse_ini_file("test.ini", true, INI_SCANNER_TYPED); var_dump($arr); ?>
実行結果は以下の様に表示されます。数値として判断できるデータは数値になっています。
array(3) { ["section1"]=> array(3) { ["data1"]=> int(1) ["data2"]=> int(1000) ["data3"]=> string(5) "abcde" } ["section2"]=> array(2) { ["string1"]=> string(6) "aaa123" ["string2"]=> string(7) "bbbbb11" } ["section3"]=> array(2) { ["array1"]=> array(3) { [0]=> string(3) "100" [1]=> int(200) [2]=> string(3) "300" } ["array2"]=> array(2) { ["test1"]=> string(8) "test1aaa" ["test2"]=> string(10) "test2bbbbb" } } }