Codeigniter(特にCodeIgniter 3)を使用した開発プロセス中に、複数のSQLクエリを含むステートメントブロック(マルチクエリ)を実行する必要がある場合があります。たとえば、複数のストアドプロシージャを一度に呼び出すか、効率を改善するために1つのリクエストで複数のクエリを実行することをお勧めします。
ただし、マルチステートメントクエリを使用する場合、一般的な問題は次のとおりです。最初の結果セットのみにアクセスでき、他の結果セットを取得できません。これは、CodeigniterがMySQLIドライバーを使用するときに複数の結果セットを自動的に処理しないためです。この問題を解決するには、 $ this-> db-> next_result()メソッドを手動で呼び出して、前の結果セットをクリーンアップし、次の結果のシステムを準備する必要があります。
この記事では、マルチステートメントクエリを処理してCodeIgniterでnext_result()を正しく使用する方法を示します。
ストアドプロシージャファイルを持っているか、コントローラーで次のようにSQLを実行するとします。
$sql = "
CALL get_users();
CALL get_orders();
";
このタイプのマルチステートメントSQLを実行するには、 query()メソッドを使用し、結果セットを手動で管理できます。
$result = $this->db->query("CALL get_users();");
if ($result) {
$users = $result->result();
// 最初の結果セットをクリーンアップします
$result->free_result();
$this->db->next_result();
// 2番目の結果セットを取得します
$result2 = $this->db->query("CALL get_orders();");
if ($result2) {
$orders = $result2->result();
// もう一度掃除します
$result2->free_result();
$this->db->next_result();
}
}
この方法は、一度に1つのストアドプロシージャのみを呼び出し、次のステートメントを手動で実行するのに適しています。ただし、複数のSQLステートメントを一度に実行したい場合、たとえば:
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
MySqliのネイティブMulti_Query()関数の助けを借りて実装できます。
Codeigniterでは、MySQLIドライバーを使用している場合、これを行うことができます。
$mysqli = $this->db->conn_id; // 基礎を取得します MySQLi リソースに接続します
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
// 現在の結果セットを処理します
$data[] = $result->fetch_all(MYSQLI_ASSOC);
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
このコードは複数の結果セットを順番に取得し、 next_result()を使用して次のコードを準備します。
Multi_Query()を直接使用できますが、特にセキュリティと安定性の要件が高い場合は、複数のステートメントを個別に実行することを強くお勧めします。データベース操作には、次のプラクティスが推奨されます。
各クエリの後にfree_result()およびnext_result()を呼び出して、接続をクリーンアップします。
モデルに複数の呼び出しを直接記述しないでください。代わりにそれらを1回の呼び出しにカプセル化すると、論理コントロールがPHPレイヤーに配置されます。
Multi_Query()を使用する必要がある場合は、返された結果セットをすべて処理し、「同期していないコマンド」エラーを回避してください。
このプロセスをモデルメソッドにカプセル化し、複数のデータセットを含む配列を返すことができます。
public function get_multi_data()
{
$mysqli = $this->db->conn_id;
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
$data = [];
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
$data[] = $result->fetch_all(MYSQLI_ASSOC);
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
return $data;
}
コントローラーでは、次のように呼ぶことができます。
$this->load->model('Data_model');
$result_sets = $this->Data_model->get_multi_data();
$users = $result_sets[0];
$orders = $result_sets[1];
$products = $result_sets[2];
マルチステートメントクエリをデバッグするときは、Codeigniterのログ機能を有効にし、アプリケーション/ログのコンテンツを観察してトラブルシューティングエラーを容易にすることをお勧めします。