Phalconのクエリビルダ(Phalcon\Mvc\Model\Criteria)備忘録

# はじめに

検索にCriteriaとfindやfindFirstの2種類がありますが、ここしばらくPhalconを使い続けてきて、ようやくCriteriaをメインに使っていこうと思い至りました。
理由はコードを見たときに分かりやすい方がCriteriaだったから。
で、使い方をすぐに忘れるので、よく使うものを備忘録として残しておきます。
[公式](https://docs.phalconphp.com/ja/latest/api/Phalcon_Mvc_Model_Criteria.html)も参照してみてください。


# 基本

Model::query()で取得できるCriteriaオブジェクトにどんどん追加していきます。

```php:1つずつ追加していく
$criteria = Books::query();
$criteria->where('name = :name:', ['name' => '広辞苑']);
$criteria->orderBy('name DESC');
$books = $criteria->execute();
```

```php:メソッドチェーンを使って一気に追加
$books = Books::query()
    ->where('name = :name:', ['name' => '広辞苑'])
    ->orderBy('name DESC')
    ->execute();
```

# メソッド

## 出力カラム
```php:文字列で指定
$criteria->columns('id,name,price');
```
```php:配列で指定
$criteria->columns(['id', 'name', 'price']);
```

## where句

### 単純な条件

> public where (unknown \$conditions, [unknown \$bindParams], [unknown \$bindTypes])

```php:whereの最初のみ使える
$criteria->where('id=:id:', ['id' => $id]);
```

```php:AND条件を追加したい時(最初に使ってもOK)
$criteria->andWhere('id=:id:', ['id' => $id]);
```

```php:OR条件を追加したい時(最初に使ってもOK)
$criteria->orWhere('id=:id:', ['id' => $id]);
```

```php:[非推奨]whereを追加
$criteria->addWhere('id=:id:', ['id' => $id]);
```

### LIKE条件
```php
$criteria->where('name LIKE :name:', ['name' => '%' . $name . '%']);
```

### IS NULL条件
```php
$criteria->where('name IS NULL');
```

### IN条件

>  inWhere (string \$expr, unknown \$values)

```php
$criteria->inWhere('id', [1, 2, 3]);
```
```php
$criteria->notInWhere('id', [1, 2, 3]);
```

### BETWEEN条件

> betweenWhere (string \$expr, unknown \$minimum, unknown \$maximum)

```php:BETWEEN
$criteria->betweenWhere('price', 100.25, 200.50);
```
```php:NOT_BETWEEN
$criteria->notBetweenWhere('price', 100.25, 200.50);
```

## ORDER BY

> orderBy (string \$orderColumns)

```php
$criteria->orderBy('id DESC,price');
```
```php:非推奨
$criteria->order('id DESC,price');
```

## GROUP BY

> groupBy (string $group)

```php
$criteria->groupBy('id');
```

## LIMIT,OFFSET

> limit (unknown \$limit, [unknown \$offset])

```php
$limit = 20;
$offset = 10;
$criteria->limit($limit, $offset);
```

## JOIN

条件を指定しない場合とかの挙動は不明。

> join (string \$model, [string \$conditions], [string \$alias], [string \$type])

```php:種別を指定するJOIN(省略時はINNER)
$criteria->join('Robots', 'r.id = RobotsParts.robots_id', 'r', 'LEFT');
```

```php:INNER_JOIN
$criteria->innerJoin('Robots', 'r.id = RobotsParts.robots_id', 'r');
```

```php:LEFT_JOIN
$criteria->leftJoin('Robots', 'r.id = RobotsParts.robots_id', 'r');
```

```php:RIGHT_JOIN
$criteria->rightJoin('Robots', 'r.id = RobotsParts.robots_id', 'r');
```

## 値のバインド

通常はwhere系の第2引数に指定するのであまり使わない。
指定数値が2つのカラムの間に存在するといったような1つの値を2か所で使う際に使う時や、第2引数に入れると見にくくなってしまう時用かな。

```php
$criteria->bind(['id' => 1, 'name' => '広辞苑']);
```

## HAVING

使ったことない。。。

```php
$criteria->having($having);
```

## メソッドで表現できない場合

使ったことない。bind()と共に使うものと思われ。

> conditions (unknown $conditions)

```php
$criteria->conditions($condition);
```

# その他・複雑な条件の場合

## カッコがついている

これでいいのか分からないがとりあえず

```php
// 開始または終了がnullの場合は無期限
$criteria->where('start<=now() OR start IS NULL');
$criteria->andWhere('now()<end OR end IS NULL');

// (start<=now() OR start IS NULL) AND (now()<end OR end IS NULL)
```

## 1件だけ取得したい(findFirst的なやつ)

いい感じのが思いつかないので、とりあえずこれ。

```php
$criteria->where('id=:id:', ['id' => $id])
    ->limit(1)
    ->execute()
    ->getFirst();
```