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');
}

関連記事

スポンサーリンク

MySQLサーバに接続できるかどうかを確認する

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

上に戻る