MySQLi(MySQL improved)はPHP5以降で利用できるMySQLの操作に関する関数群を提供する拡張モジュールで、MySQL 4.1.3以降の新機能を利用できるよう開発されたものである。旧来のMySQLモジュールと比較して、以下の特徴を備えている[1]。
従来型MySQLモジュールによる記述をMySQLiモジュールによるに変換するには、手続き型インタフェースを使った方が楽かも知れません。多くの場合、関数の前半部を「mysql_」から「mysqli_」に変更するだけで済むでしょう。但し、いくつかの関数でデータベース接続ハンドルの指定の位置が変わります。従来型では最後の引数に指定していたのに対し、MySQLiでは最初の引数として指定する必要があります[2]。
【MySQL】 $mysql = mysql_connect('localhost','user','pass'); mysql_select_db('sampledb'); $result_src = mysql_query('SELECT * FROM sampletbl',$mysql); $result = mysql_fetch_assoc($result_src); print_r($result); 【MySQLi】 $mysqli = mysqli_connect('localhost','user','pass','sampledb'); $result_src = mysqli_query($mysqli,'SELECT * FROM sampletbl'); $result = mysqli_fetch_assoc($result_src); print_r($result);
MySQLiを利用するにはビルド時に有効となるよう指定しておく必要がある[3]。
データベースに問い合わせた結果の受け取り方には「Buffered」と「Unbuffered」の2種類がある。Bufferedは結果を一度に受け取る方法。サーバの負担は小さくなるが、結果が多いとメモリ不足に陥る恐れがある。Unbufferedは結果を1つずつ受け取る方法。サーバには負担をかけるがクライアント側でメモリ不足が起きる可能性は減る。一般的には「Buffered」を使い、結果が大量になるなど「Buffered」で支障がある場合にのみ「Unbuffered」を使うことが推奨される[4]。
プリペアドステートメント(prepared statement)によりMySQLサーバに接続することができる。これを使うと以下の利点がある。
プリペアドステートメントを使った手順は以下の通り。
mysqli::__construct
)mysqli_stmt::prepare
)mysqli_stmt::bind_param
)mysqli_stmt::execute
)mysqli_stmt::bind_result
)mysqli_stmt::fetch
)mysqli_stmt::close
)mysqli::close
)【例】オブジェクト指向型 <?php /* 1. データベース接続 */ $mysqli = new mysqli("example.com", "user", "password", "database"); if ($mysqli->connect_errno) { echo "MySQLデータベースへの接続に失敗しました: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error; exit; } /* 2. ステートメント準備 */ if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) { echo "準備に失敗しました: (" . $mysqli->errno . ") " . $mysqli->error; } /* 3. パラメータの接続 */ $id = 1; if (!$stmt->bind_param("i", $id)) { echo "パラメータの接続に失敗しました: (" . $stmt->errno . ") " . $stmt->error; } /* 4. ステートメント実行 */ if (!$stmt->execute()) { echo "実行に失敗しました: (" . $stmt->errno . ") " . $stmt->error; } /* 2. ステートメント準備 */ if (!($stmt = $mysqli->prepare("SELECT id FROM test"))) { echo "準備に失敗しました: (" . $mysqli->errno . ") " . $mysqli->error; } /* 4. ステートメント実行 */ if (!$stmt->execute()) { echo "実行に失敗しました: (" . $stmt->errno . ") " . $stmt->error; } /* 5. 結果変数を接続 */ if (!$stmt->bind_result($id)) { echo "実行に失敗しました: (" . $stmt->errno . ") " . $stmt->error; } /* 6. 値を取得 */ while ($stmt->fetch()) { printf("%s\n",$id); } /* 7. ステートメントを閉じる */ $stmt->close(); /* 8. 接続を閉じる */ $mysqli->close(); ?>
【例】手続き型 <?php /* 1. データベース接続 */ $link = mysqli_connect("example.com", "user", "password", "database"); if (mysqli_connect_errno()) { echo "MySQLデータベースへの接続に失敗しました: (" . mysqli_connect_errno() . ") " . mysqli_connect_error(); exit; } /* 2. ステートメント準備 */ $stmt = mysqli_prepare($link,"INSERT INTO test(id) VALUES (?)"); if (!$stmt) { echo "準備に失敗しました: (" . mysqli_errno($link) . ") " . mysqli_error($link); } /* 3. パラメータの接続 */ $id = 1; if (!(mysqli_stmt_bind_param($stmt,"i", $id))) { echo "パラメータの接続に失敗しました: (" . mysqli_stmt_errno($stmt) . ") " . mysqli_stmt_error($stmt); } /* 4. ステートメント実行 */ if (!(mysqli_stmt_execute($stmt))) { echo "実行に失敗しました: (" . mysqli_stmt_errno($stmt) . ") " . mysqli_stmt_error($stmt); } /* 2. ステートメント準備 */ $stmt = mysqli_prepare($link,"SELECT id FROM test"); if (!$stmt) { echo "準備に失敗しました: (" . mysqli_errno($link) . ") " . mysqli_error($link); } /* 4. ステートメント実行 */ if (!(mysqli_stmt_execute($stmt))) { echo "実行に失敗しました: (" . mysqli_stmt_errno($stmt) . ") " . mysqli_stmt_error($stmt); } /* 5. 結果変数を接続 */ if (!(mysqli_stmt_bind_result($id))) { echo "実行に失敗しました: (" . mysqli_stmt_errno($stmt) . ") " . mysqli_stmt_error($stmt); } /* 6. 値を取得 */ while (mysqli_stmt_fetch($stmt)) { printf("%s\n",$id); } /* 7. ステートメントを閉じる */ mysqli_stmt_close($stmt); /* 8. 接続を閉じる */ mysqli_close($link); ?>
MySQL版のコマンドmysql_connectについてはこちら。
mysqli::__constructによりMySQLサーバに接続することができる。手続き型とオブジェクト指向型の2通りの書き方ができる。
手続き型の場合、mysqli_connect関数を実行する。オブジェクト指向型の場合、mysqliクラスのオブジェクトを作成する。
<オブジェクト指向型> 【書式】 new mysqli (MySQLサーバ名,MySQLユーザ名,MySQLユーザのパスワード,MySQLデータベース名,MySQL接続先ポート番号,MySQL接続ソケット名) 【返り値】 MySQL サーバーへの接続を表すオブジェクト ※接続に失敗してもオブジェクトが返される。 接続が失敗したかどうかを確認するにはmysqli_connect_error()
関数、またはmysqli->connect_error
プロパティを使用する。 <手続き型> 【書式】 mysqli_connect (MySQLサーバ名,MySQLユーザ名,MySQLユーザのパスワード,MySQLデータベース名,MySQL接続先ポート番号,MySQL接続ソケット名) 【返り値】 MySQL サーバーへの接続リソース(リンクid)
【例】ローカルシステムのmydbにユーザdbuser、パスワードdbpassで接続 <オブジェクト指向型> $mysqli = new mysqli('localhost','dbuser','dbpass','mydb'); <手続き型> $link = mysqli_connect('localhost','dbuser','dbpass','mydb');
接続先MySQLサーバを示すホスト名または IP アドレスを指定する。この引数に NULL または "localhost" を指定するとローカルホストが指定されたものとみなされる。もし可能な場合、TCP/IP プロトコルの代わりに パイプが使用される。
ホストの前に「p:
」をつけると、持続的な接続を開く。接続プールから開いた接続上で mysqli_change_user()
が自動的にコールされる。
データ型は文字列。指定がない場合の既定値は設定オプション「mysqli.default_host」の返す値。
MySQL版のコマンドmysql_closeについてはこちら。
mysqli::closeはMySQLサーバへの接続を切断する。手続き型とオブジェクト指向型の2通りの書き方ができる。
<オブジェクト指向型> 【書式】 mysqliオブジェクト->close(); <手続き型> 【書式】 mysql_close(MySQLデータベースリンクid) 【返り値】 MySQL接続切断成功→true それ以外→false
mysqli_connect
、またはmysqli_init
によって開かれたMySQL接続id。
mysqli_set_charsetはデータベースサーバーとのデータの送受信に使用する文字コードを指定する。
【書式】オブジェクト指向型 mysqli->set_charset(文字コード名) 【書式】手続き型 mysqli_set_charset (リンクid,文字コード名) 【返り値】 設定に成功→TRUE 失敗→FALSE
MySQL版のコマンドmysql_select_dbについてはこちら。
mysqli_select_dbはクエリを実行するためのデフォルトデータベースを変更する。書式は以下の通り。なおデフォルトデータベースはmysqli_connectでも指定可能。
【書式】オブジェクト指向型 mysqli->select_db(データベース名) 【書式】手続き型 mysqli_select_db (リンクid,データベース名) 【返り値】 データベースの選択に成功→TRUE 失敗→FALSE
mysqlプロンプトでコマンド「USE 'データベース名'
」を実行することに相当(→MySQL関係 - 使用データベース選択)。
MySQL版のコマンドmysql_queryについてはこちら。
mysqli_queryは、MySQLサーバに対してクエリを送信する。書式は以下の通り。
【書式】オブジェクト指向型 mysqli->query(クエリ文字列,結果モード) 【書式】手続き型 mysqli_query(リンクid,クエリ文字列,結果モード) 【返り値】 SELECT、SHOW、DESCRIBE、EXPLAINなど結果を返すクエリ:成功→mysqli_resultオブジェクト(結果リソース)、失敗→false INSERT、UPDATE、DELETE、DROPなど結果を返さないクエリ:成功→true、失敗→false ※テーブルに対するアクセス権がない場合などもfalseが返る
mysql_real_escape_string
を用いてエスケープ処理をすべき。
定数「MYSQLI_USE_RESULT」または「MYSQLI_STORE_RESULT」 のどちらかで指定。指定がない場合の既定値は「MYSQLI_STORE_RESULT」。
「MYSQLI_USE_RESULT」を指定すると、mysqli_free_result()
を実行するまで、以降のmysqli_queryの実行に対して「Commands out of sync」エラーを返す。
MYSQLI_ASYNC (mysqlnd で使用可能) を使用すると、クエリを非同期実行できるようになります。 このクエリの結果を取得するには mysqli_poll() を使用します。
事例はこちら
MySQL版のコマンドmysql_fetch_array/assoc/rowについてはこちら。
mysqli_fetch_array、mysqli_fetch_row、mysqli_fetch_assocは、mysqli_queryで発行したクエリ要求の結果を1件ずつ取得する。返り値となる配列のキーは以下の通り。1件取得するとポインタが次へ移動し、再度コマンドを発行すると次の1件が返る。もうこれ以上条件にマッチする結果がない場合や、1件もヒットしなかった場合はNULLが返る。
【書式】オブジェクト指向型 mysqli_result::fetch_array(結果の配列様式); 【書式】手続き型 mysqli_fetch_array(結果リソース,結果の配列様式) 【返り値】 結果がある時→取得行に対応する配列 結果がもうない時→NULL ※MySQL関数ではfalseが返されていた
コマンド | 内容 | |
---|---|---|
添字配列 | 連想配列 | |
mysqli_fetch_array(結果リソース,MYSQL_BOTH) |
○ | ○ |
mysqli_fetch_array(結果リソース,MYSQL_NUM) |
○ | − |
mysqli_fetch_row(結果リソース) |
○ | − |
mysqli_fetch_array(結果リソース,MYSQL_ASSOC) |
− | ○ |
mysqli_fetch_assoc(結果リソース) |
− | ○ |
結果が必要なくなったら、mysqli_free_resultでメモリを開放する方がよい。
例: Array ( [0] => 1 [1] => 2000 [2] => 1 [3] => ミオグロビン [4] => Myoglobin )
例: Array ( [momid] => 1 [year] => 2000 [month] => 1 [janame] => ミオグロビン [enname] => Myoglobin )
例: Array ( [0] => 1 [1] => 2000 [2] => 1 [3] => ミオグロビン [4] => Myoglobin [momid] => 1 [year] => 2000 [month] => 1 [janame] => ミオグロビン [enname] => Myoglobin )
mysql> SELECT pdbid,ec FROM ec; +-------+----------+ | pdbid | ec | +-------+----------+ | 1ldm | 1.1.1.27 | | 2jhg | 1.1.1.1 | | 8cat | 1.11.1.6 | | 1ppi | 3.2.1.1 | | 1ca2 | 4.2.1.1 | +-------+----------+ <pdb.php> <?php #- mysql接続 $link = mysqli_connect('localhost','hoge',NULL,'pdb'); #- クエリ文定義 $query_str = "SELECT pdbid,ec FROM ec WHERE pdbid='2jhg'"; #- クエリ文発行 $result_src = mysqli_query($link,$query_str); #- 結果1件取得 $result = mysqli_fetch_array($result_src); echo "2jhg:\n"; print_r($result); $query_str = "SELECT pdbid,ec FROM ec WHERE pdbid='9jhg'"; $result_src = mysqli_query($link,$query_str); $result = mysqli_fetch_array($result_src); echo "9jhg:\n"; print_r($result); ?> <結果> 2jhg: Array ( [pdbid] => 2jhg [ec] => 1.1.1.1 ) 9jhg: Array ( )
mysqli_free_resultは結果用に確保されたメモリを開放する。
【書式】オブジェクト指向型
mysqli_result::free()
mysqli_result::close()
mysqli_result::free_result()
【書式】手続き型
mysqli_free_result(結果リソース)
【返り値】なし
オブジェクト指向型の例
$ cat test_object.php <?php /* MySQLサーバに接続 * 接続先ホストは localhost * MySQL接続ユーザ名はmuser * MySQL接続ユーザパスワードはmpass * 接続先データベース名はmydb */ $mysqli = new mysqli('localhost','muser','mpass','mydb'); /* * 接続に失敗したらエラー番号とエラー内容を出力して終了 */ if ($mysqli->connect_error) { die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error); } /* * PHP 5.2.9 および PHP 5.3.0 以前との互換を保つ方法は以下の通り */ if (mysqli_connect_error()) { die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); } echo 'MySQLデータベースオープンに成功しました。' . $mysqli->host_info . "\n"; /* 既定の文字コードをutf-8にセット */ $mysqli->set_charset("utf8"); /* クエリ文字列定義 */ $query_str = 'SELECT * from kintetsu_nara'; /* クエリ送信成功 */ if ($result = $mysqli->query($query_str)) { /* 結果がなくなるまで受信 */ while (($row = $result->fetch_assoc()) != NULL) { echo sprintf('%s:%s',$row['sid'],$row['sname'])."\n"; } /* 結果用に確保されたメモリの開放 */ $result->free(); } /* MySQLサーバへの接続終了 */ $mysqli->close();
手続き型の例
$ cat test_procedure.php <?php /* MySQLサーバに接続 * 接続先ホストは localhost * MySQL接続ユーザ名はmuser * MySQL接続ユーザパスワードはmpass * 接続先データベース名はmydb */ $link = mysqli_connect('localhost','muser','mpass','mydb'); /* * 接続に失敗したらエラー番号とエラー内容を出力して終了 */ if (mysqli_connect_error()) { die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); } echo 'MySQLデータベースオープンに成功しました。' . mysqli_get_host_info($link) . "\n"; /* 既定の文字コードをutf-8にセット */ mysqli_set_charset("utf8"); /* クエリ文字列定義 */ $query_str = 'SELECT * from kintetsu_nara'; /* クエリ送信成功 */ if ($result = mysqli_query($link,$query_str)) { /* 結果がなくなるまで受信 */ while (($row = mysqli_fetch_assoc($result)) != NULL) { echo sprintf('%s:%s',$row['sid'],$row['sname'])."\n"; } /* 結果用に確保されたメモリの開放 */ mysqli_free($result); } /* MySQLサーバへの接続終了 */ mysqli_close($link);
実行結果
$ php test_object.php MySQLデータベースオープンに成功しました。Localhost via UNIX socket A01:大阪難波 A02:近鉄日本橋 A03:大阪上本町 A04:鶴橋 A05:今里 A06:布施 A07:河内永和 A08:河内小阪 A09:八戸ノ里 A10:若江岩田 A11:東花園 A12:河内花園 A13:瓢箪山 A14:枚岡 A15:額田 A16:石切 A17:生駒 A18:東生駒 A19:富雄 A20:学園前 A21:菖蒲池 A26:大和西大寺 A27:新大宮 A28:近鉄奈良