SQLクエリー(SQL文)を直接実行する方法

SQL文を直接実行する方法
SQL文でパラメーターをエスケープする方法
SQL言語によって切り替える方法

SQL文を直接実行する方法

SQL文を直接実行する場合、以前はモデルクラスのqueryメソッドでしたがCakePHP4ではConnectionManagerクラスのexecuteまたはqueryで実行します。

use Cake\Datasource\ConnectionManager;

……
…
……

$connection = ConnectionManager::get('default');
$connection->execute("【SQL文】")->fetchAll('assoc');
または
$connection = ConnectionManager::get('default');
$connection->query("【SQL文】")->fetchAll('assoc');

executeは次の項のプリペアードステートメントが使えますが、queryは使えません。

SQL文でパラメーターをエスケープする方法

パラメーターを渡すには、プリペアードステートメントを使います。

$results = $connection
    ->execute('SELECT * FROM articles WHERE id = :id', ['id' => 1])
    ->fetchAll('assoc');

プリペアードステートメントを使わずにパラメータを直接記述するとSQLインジェクション攻撃の危険性が出てきます。
このためqueryではなくexecuteを使うのが正しい記法です。
またqueryを使わざる得ないときやプリペアードステートメントでエスケープできない場合は、PHPの文字置き換えなどを使用せずCakePHPのクエリビルダーでエスケープするのが正しいです。

SQL言語によって切り替える方法

SQL言語によってSQLの記法は異なり、ORMを使用すればその差異は吸収されます。
しかしSQL文を直接記述する場合はそのSQL言語のみで実行させるようなケースが起こりえます。

config/app.phpに記載されている設定値は次のようにして得られます。

$connection = ConnectionManager::get('default');
debug($connection->config());

このうちドライバは$connection->config()['driver']です。

'driver' => Mysql::class,'Cake\Database\Driver\Mysql'
'driver' => Postgres::class,'Cake\Database\Driver\Postgres'
'driver' => Sqlite::class,'Cake\Database\Driver\Sqlite'
'driver' => Sqlserver::class,'Cake\Database\Driver\Sqlserver'

例えばPostgreSQLは次のようにして分岐できます。
PostgreSQLではシーケンスによりプライマリキーの自動採番を行うため、用途によってはPostgreSQLだけで使用するSQLの実行は多いです。

$connection = ConnectionManager::get('default');
if (strpos(strtolower($connection->config()['driver']), 'postgres') !== false) {
    $connection->execute("【PostgreSQLのみで実行されるSQL文】")->fetchAll('assoc');
}

関連記事

スポンサーリンク

相対配置した要素へ向かうリンクのジャンプ先が移動前の位置になる

ホームページ製作・web系アプリ系の製作案件募集中です。

上に戻る