クエリ
クエリの基本
注記
CodeIgniter は、データベース、テーブル、カラム名にドット (.
) をサポートしていません。
通常のクエリ
$db->query()
クエリを送信するには、query()
メソッドを使用します
<?php
$db = db_connect();
$db->query('YOUR QUERY HERE');
query()
メソッドは、「読み取り」タイプのクエリが実行されるとデータベース結果 ** オブジェクト ** を返し、これを使用して結果を表示できます。「書き込み」タイプのクエリが実行されると、成功または失敗に応じて単純に true または false が返されます。データを取得する場合、通常は次のようにクエリを独自の変数に代入します
<?php
$query = $db->query('YOUR QUERY HERE');
注記
OCI8 ドライバーを使用している場合、SQL ステートメントはセミコロン (;
) で終わらせてはいけません。PL/SQL ステートメントはセミコロン (;
) で終わらせる必要があります。
簡略化されたクエリ
$db->simpleQuery()
simpleQuery()
メソッドは、$db->query()
メソッドの簡略化されたバージョンです。データベース結果セットを返しません。また、クエリタイマーの設定、バインドデータのコンパイル、デバッグのためのクエリの保存も行いません。単純にクエリを送信できます。ほとんどのユーザーはこの関数を使用することはめったにありません。
データベースドライバーの「execute」関数が返すものを返します。これは通常、INSERT、DELETE、UPDATE などの書き込みタイプのクエリ(実際に使用する必要があるもの)の成功または失敗の場合は true/false であり、フェッチ可能な結果を持つクエリの成功の場合はリソース/オブジェクトです。
<?php
if ($db->simpleQuery('YOUR QUERY')) {
echo 'Success!';
} else {
echo 'Query failed!';
}
注記
たとえば、PostgreSQL の pg_exec()
関数は、書き込みタイプのクエリであっても、成功時には常にリソースを返します。そのため、ブール値を探している場合は、それを覚えておいてください。
データベースプレフィックスの手動操作
$db->prefixTable()
データベースプレフィックスを設定していて、ネイティブ SQL クエリで使用するためにテーブル名の前にプレフィックスを追加したい場合は、次を使用できます
<?php
$db->prefixTable('tablename'); // outputs prefix_tablename
$db->setPrefix()
何らかの理由で、新しい接続を作成せずにプログラムでプレフィックスを変更したい場合は、このメソッドを使用できます
<?php
$db->setPrefix('newprefix_');
$db->prefixTable('tablename'); // outputs newprefix_tablename
$db->getPrefix()
このメソッドを使用して、いつでも現在のプレフィックスを取得できます
<?php
$DBPrefix = $db->getPrefix();
識別子の保護
$db->protectIdentifiers()
多くのデータベースでは、テーブル名とフィールド名を保護することをお勧めします。たとえば、MySQL ではバッククォートを使用します。 ** クエリビルダーのクエリは自動的に保護されます ** が、識別子を手動で保護する必要がある場合は、次を使用できます
<?php
$db->protectIdentifiers('table_name');
重要
クエリビルダーは、フィードされたフィールド名とテーブル名を適切に引用しようとしますが、任意のユーザー入力で動作するように設計されていませんのでご注意ください。サニタイズされていないユーザーデータを入力しないでください。
この関数は、データベース設定ファイルでプレフィックスが指定されていると仮定して、テーブルに ** テーブルプレフィックス ** も追加します。プレフィックスを有効にするには、2 番目のパラメーターを介して true
(ブール値)を設定します
<?php
$db->protectIdentifiers('table_name', true);
値のエスケープ
データをデータベースに送信する前にエスケープすることは、非常に優れたセキュリティ対策です。CodeIgniter には、これを行うのに役立つ 3 つのメソッドがあります
1. $db->escape()
この関数はデータ型を判別して、文字列データのみをエスケープできるようにします。また、データの周りに自動的に単一引用符を追加するため、手動で追加する必要はありません
<?php
$sql = 'INSERT INTO table (title) VALUES(' . $db->escape($title) . ')';
2. $db->escapeString()
この関数は、型に関係なく、渡されたデータをエスケープします。ほとんどの場合、この関数ではなく上記の関数を使用します。関数は次のように使用します
<?php
$sql = "INSERT INTO table (title) VALUES('" . $db->escapeString($title) . "')";
3. $db->escapeLikeString()
このメソッドは、文字列が LIKE 条件で使用される場合に、文字列内の LIKE ワイルドカード (%
、_
) も適切にエスケープされるように使用されます。
<?php
$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" . $db->escapeLikeString($search) . "%' ESCAPE '!'";
重要
escapeLikeString()
メソッドは、LIKE
条件の特殊文字をエスケープするために '!'
(感嘆符)を使用します。このメソッドは、自分で引用符で囲む部分文字列をエスケープするため、ESCAPE '!'
条件を自動的に追加することはできません。そのため、手動で追加する必要があります。
クエリバインディング
バインディングを使用すると、システムがクエリをまとめて作成できるため、クエリ構文を簡略化できます。次の例を考えてみましょう
<?php
$sql = 'SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?';
$db->query($sql, [3, 'live', 'Rick']);
クエリの疑問符は、クエリ関数の 2 番目のパラメーターの配列の値に自動的に置き換えられます。
バインディングは配列でも機能し、IN セットに変換されます
<?php
$sql = 'SELECT * FROM some_table WHERE id IN ? AND status = ? AND author = ?';
$db->query($sql, [[3, 6], 'live', 'Rick']);
結果のクエリは次のようになります
SELECT * FROM some_table WHERE id IN (3,6) AND status = 'live' AND author = 'Rick'
バインディングを使用する 2 番目の利点は、値が自動的にエスケープされて、より安全なクエリが生成されることです。データを手動でエスケープする必要はありません。エンジンが自動的に実行します。
名前付きバインディング
疑問符を使用してバインドされた値の場所をマークする代わりに、バインディングに名前を付けることができます。これにより、渡される値のキーがクエリ内のプレースホルダーと一致するようになります
<?php
$sql = 'SELECT * FROM some_table WHERE id = :id: AND status = :status: AND author = :name:';
$db->query($sql, [
'id' => 3,
'status' => 'live',
'name' => 'Rick',
]);
注記
クエリ内の各名前はコロンで囲む必要があります。
エラー処理
$db->error()
発生した最後のエラーを取得する必要がある場合、error()
メソッドは、そのコードとメッセージを含む配列を返します。簡単な例を次に示します
<?php
if (! $db->simpleQuery('SELECT `example_field` FROM `example_table`')) {
$error = $db->error(); // Has keys 'code' and 'message'
}
プリペアドクエリ
ほとんどのデータベースエンジンは、何らかの形式のプリペアドステートメントをサポートしています。これにより、クエリを一度準備し、新しいデータセットでそのクエリを複数回実行できます。データはクエリ自体とは異なる形式でデータベースに渡されるため、SQLインジェクションの可能性が排除されます。同じクエリを複数回実行する必要がある場合、かなり高速になる可能性もあります。ただし、すべてのクエリにこれを使用すると、データベースを2倍の頻度で呼び出すため、パフォーマンスが大幅に低下する可能性があります。クエリビルダーとデータベース接続はすでにデータのエスケープを処理しているため、安全性の側面はすでに考慮されています。ただし、プリペアドステートメントまたはプリペアドクエリを実行することでクエリを最適化する必要がある場合があります。
クエリの準備
これは、prepare()
メソッドで簡単に実行できます。これは、クエリオブジェクトを返すクロージャである単一のパラメータを取ります。クエリオブジェクトは、**insert**、**update**、**delete**、**replace**、**get** を含む、あらゆる「最終」タイプのクエリによって自動的に生成されます。これは、クエリビルダーを使用してクエリを実行するのが最も簡単です。クエリは実際には実行されず、値は適用されないため、プレースホルダーとして機能します。これはPreparedQueryオブジェクトを返します
<?php
$pQuery = $db->prepare(static function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US',
]);
});
クエリビルダーを使用したくない場合は、値のプレースホルダーに疑問符を使用してクエリオブジェクトを手動で作成できます
<?php
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(static function ($db) {
$sql = 'INSERT INTO user (name, email, country) VALUES (?, ?, ?)';
return (new Query($db))->setQuery($sql);
});
データベースがプリペアドステートメントフェーズ中に渡されるオプションの配列を必要とする場合は、2番目のパラメータでその配列を渡すことができます
<?php
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(static function ($db) {
$sql = 'INSERT INTO user (name, email, country) VALUES (?, ?, ?)';
return (new Query($db))->setQuery($sql);
}, $options);
クエリの実行
プリペアドクエリを作成したら、execute()
メソッドを使用してクエリを実際に実行できます。クエリパラメータに必要な数の変数を渡すことができます。渡すパラメータの数は、クエリ内のプレースホルダーの数と一致する必要があります。また、プレースホルダーが元のクエリに表示されるのと同じ順序で渡す必要があります
<?php
// Prepare the Query
$pQuery = $db->prepare(static function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US',
]);
});
// Collect the Data
$name = 'John Doe';
$email = '[email protected]';
$country = 'US';
// Run the Query
$results = $pQuery->execute($name, $email, $country);
「書き込み」タイプのクエリの場合、クエリの成功または失敗を示すtrueまたはfalseを返します。「読み取り」タイプのクエリの場合、標準の 結果セット を返します。
その他のメソッド
これらの2つの主要なメソッドに加えて、プリペアドクエリオブジェクトには次のメソッドもあります
close()
PHPはデータベースで開いているすべてのステートメントを閉じるのに非常に優れていますが、プリペアドステートメントを使い終わったら閉じることをお勧めします
<?php
if ($pQuery->close()) {
echo 'Success!';
} else {
echo 'Deallocation of prepared statements failed!';
}
注記
v4.3.0以降、close()
メソッドは、すべてのDBMSでプリペアドステートメントの割り当てを解除します。以前は、Postgre、SQLSRV、およびOCI8では割り当て解除されていませんでした。
getQueryString()
これは、プリペアドクエリを文字列として返します。
hasError()
最後の execute()
呼び出しでエラーが発生した場合、ブール値true / falseを返します。
getErrorCode()
getErrorMessage()
エラーが発生した場合、これらのメソッドを使用してエラーコードと文字列を取得できます。
クエリオブジェクトの操作
内部的には、すべてのクエリは CodeIgniter\Database\Query
のインスタンスとして処理および格納されます。このクラスは、パラメータのバインド、クエリの準備、およびクエリに関するパフォーマンスデータの格納を担当します。
$db->getLastQuery()
最後のクエリオブジェクトを取得する必要がある場合は、getLastQuery()
メソッドを使用します
<?php
$query = $db->getLastQuery();
echo (string) $query;
クエリクラス
各クエリオブジェクトは、クエリ自体に関するいくつかの情報を格納します。これは、一部はタイムライン機能で使用されますが、ユーザーも使用できます。
getQuery()
すべての処理が行われた後の最終的なクエリを返します。これは、データベースに送信された正確なクエリです
<?php
$sql = $query->getQuery();
クエリオブジェクトを文字列にキャストすることによっても、同じ値を取得できます
<?php
$sql = (string) $query;
getOriginalQuery()
オブジェクトに渡された生のSQLを返します。これにはバインド、プレフィックスの入れ替えなどは含まれません
<?php
$sql = $query->getOriginalQuery();
hasError()
このクエリの実行中にエラーが発生した場合、このメソッドはtrueを返します
<?php
if ($query->hasError()) {
echo 'Code: ' . $query->getErrorCode();
echo 'Error: ' . $query->getErrorMessage();
}
isWriteType()
クエリが書き込みタイプのクエリ(INSERT、UPDATE、DELETEなど)と判断された場合、trueを返します
<?php
if ($query->isWriteType()) {
// ... do something
}
swapPrefix()
SQL内の1つのテーブルプレフィックスを別の値に置き換えます。最初のパラメータは置き換えたい元のプレフィックスで、2番目のパラメータは置き換えたい値です
<?php
$sql = $query->swapPrefix('ci3_', 'ci4_');
getStartTime()
クエリが実行された時刻をマイクロ秒単位の秒で取得します
<?php
$microtime = $query->getStartTime();
getDuration()
クエリの期間をマイクロ秒単位の秒で表す浮動小数点数を返します
<?php
$microtime = $query->getDuration();