2023.11.10

CakePHP

CakePHP3 クエリービルダーの使用例

クエリーオブジェクトを使用して、SQLクエリーを組み立てることで、直接SQL文を記述する必要が無くなるので、RDBMS環境に依存せずに、データベースを操作することができます。

●Controllerで新しいクエリーを作成する例
cake phpの監修に従ってModel、Controllerを作成していれば、以下のようにテーブル変数からfind()を使用します。

$countries = $this->Countries->find();

●Tableで新しいクエリーを作成する例
Tableオブジェクトからfind()を使用します。

use Cake\ORM\TableRegistry;

$countries = TableRegistry::getTableLocator()->get('Countries');

$query= $countries->find();

●クエリーは次のいずれかが呼ばれると実行されます
foreach()、execute()、first()、all()、toList()、toArray()

●以下が使用例です。

//アジア大陸に属する国名、リージョン、人口を取得し、人口の降順で並び替える
//SELECT name, region, population FROM countries WHERE continent = 'Asia' ORDER BY population DESC;
$this->Countries
    ->find()
    ->select(['name', 'region', 'population'])
    ->where(['continent' => 'Asia'])
    ->order(['population' => 'DESC']);
//国コードがCOL(コロンビア)のレコードを1件取得する
//SELECT code, name, continent, region, surface_area, indep_year, population, life_expectancy, gnp, gnp_old, local_name, government_form, head_of_state, capital, code2 FROM countries WHERE code = 'COL' LIMIT 1;
$this->Countries
    ->find()
    ->where(['code' => 'COL'])
    ->first();
//クエリーの結果からlocal_nameカラムの値のみ取得する
$this->Countries
    ->find()
    ->extract('local_name');
//クエリーの結果から連想配列で値を取得する
//SELECT Code FROM countries;
$this->Countries->find('list');
//フィールドのエイリアス (別名) をセット
//SELECT code AS 'pk', region AS 'aliased_region', population FROM countries;
$this->Countries->find()
 ->select([
    'pk' => 'code',
    'aliased_region' => 'region',
    'population'
]);
//重複した独立年を一つにまとめる
//SELECT indep_year FROM countries GROUP BY indep_year;
$this->Countries
    ->find()
    ->select(['indep_year'])
    ->distinct(['indep_year']);

//ヨーロッパ大陸かつリージョンが西ヨーロッパまたは独立年が1918年の国データを取得
//SELECT * FROM countries WHERE continent = "Europe" AND (region = 'Western Europe' OR indep_year = '1918');
$this->Countries
    ->find()
    ->where([
        'continent' => 'Europe',
        'OR' => [['region' => 'Western Europe'], ['indep_year' => 1918]],
    ]);

Where()をQueryExpressionクラスを使って定義することで、詳細なWHERE句を作成することができます。

//ヨーロッパ大陸かつリージョンが西ヨーロッパかつ国名がユーゴスラビアではなく、人口が10000000より大きい国データを取得
//SELECT * FROM countries WHERE ( continent = 'Europe' AND region = 'Western Europe' AND name != 'Yugoslavia' AND population > 10000000);
$this->Countries
    ->find()
    ->where(function (QueryExpression $exp) {
        return $exp
            ->eq('continent', 'Europe')
            ->eq('region', 'Western Europe')
            ->notEq('name', 'Yugoslavia')
            ->gt('population', 10000000);
    });
//ロケール名にIslandsを含み、国名にNorthが含まれる国のレコードを取得
//SELECT * FROM countries WHERE local_name LIKE '%Islands%' AND name NOT LIKE '%North%';
$this->Countries->find()
    ->where(function (QueryExpression $exp, Query $q) {
        return $exp
            ->like('local_name', '%Islands%')
            ->notLike('name', '%North%');
    });
//国コードがCCK JPN VMN(ココス諸島、日本、ベトナム)のレコードを取得
//SELECT * FROM countries WHERE code IN ('CCK', 'JPN', 'VNM');
$this->Countries->find()
    ->where(function (QueryExpression $exp, Query $q) {
        return $exp->in('code', ['CCK', 'JPN', 'VNM']);
    });
//countriesのcapitalがNULLのレコードを含めた、国名、都市名を取得する
//SELECT countries.name, cities.name FROM countries LEFT JOIN cities ON countries.capital = cities.id;
$this->Countries->find()
    ->Join([
        'table' => 'cities',
        'type' => 'LEFT',
        'conditions' => 'Countries.capital = cities.id'
    ])
    ->select(['Countries.name', 'cities.name']);
//countriesのcapitalがNULLのレコードを省いた都市の数をカウントする
//SELECT COUNT(*) FROM countries JOIN cities ON countries.capital = cities.id;
$query = $this->Countries->find();
$query->select(['total_countries' => $query->func()->count('*')])
    ->join([
        'table' => 'cities',
        'conditions' => 'Countries.capital = cities.id'
    ]);

CakePHPではなじみのSQL関数が func() メソッドとともに使えます。
sum()、avg()、min()、max()、concat()、coalesce()、dateDiff()、now()、extract()、dateAdd()、 dayOfWeek() etc…