CakePHP4 のクエリビルダで実装されていないMySQL関数はマジックメソッドでそのまま実行される

[[MySQL][CakePHP4] GROUP_CONCAT でカラム値を連結したい＆group_concat_max_len システム変数](https://qiita.com/mamy1326/items/a0e476fd0620b3921d0c)
の続きです。

# 結論

- 2020年11月29日時点で CakePHP4 には GROUP_CONCAT 関数は実装されていない
- マジックメソッドにより[MySQL の関数を直接実行する](https://github.com/cakephp/cakephp/blob/master/src/Database/FunctionsBuilder.php#L347-L359)ので `group_concat` と書けば動く
- postgreSQL, SQL Server, SQLite に対し、[機能追加の PR](https://github.com/cakephp/cakephp/pull/14620) が出ているがまだマージされていない
- よって、MySQL 以外はまだ使えない
- マージされたら RDBMS の種類関係なくキャメルケースの `groupConcat` として使える

# GROUP_CONCAT の PR
[@ktou](https://twitter.com/ktou)さんが調べてくださった [CakePHP4 の GROUP_CONCAT の PR](https://github.com/cakephp/cakephp/pull/14620/files#diff-49f82f873281dbcfe89fd4b925b46d880036a3e466bad8f4f9f905d14db982a1R363) を読んでいて、なるほど MySQL はおそらくそのまま関数を実行していて、他のRDBMS では実行できないから PR 出されているんだな、と理解はしてたのですが、実際のコードと動きから実証したわけではありませんでした。
が、なんと引き続き調べてくださっていました。圧倒的感謝…
よって流れをまとめさせていただきます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">さすがです！group_concatがCakePHPの公式ドキュメントには載っていないということなので公式ドキュメントにも追加するのが私のオススメです！ところで、 <a href="https://t.co/ScMFIoKfHX">https://t.co/ScMFIoKfHX</a> がまだ作業中なので使えなそうな気がするんですが、なんで使えるんでしょうね。。。</p>&mdash; す (@ktou) <a href="https://twitter.com/ktou/status/1326712267795128325?ref_src=twsrc%5Etfw">November 12, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

僕も疑問だったんですが、軽く CakePHP4 本体のコードを追っていたら、CakePHP4 自体に存在しない関数はそのまま MySQL の関数を呼んでそう…と予測するところで考えるのをやめてしまってました。

そうしたら、なんと引き続きコードを追ってくださっていて…なんかもう僕がコードを追わせてしまった感じになっていて申し訳ない限りなのですが、これはもう感謝しかないということで Qiita に投稿している次第です。TL に埋もれさせてはいかん。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">なるほど！私も確認してみました！FunctionsBuilderは未知のAPIでも関数を呼べるようになっていました！ <a href="https://t.co/WuL6UBN7qH">https://t.co/WuL6UBN7qH</a> なので、-&gt;group_concat()とMySQLで呼ばれるような関数の書き方をしたら動いていたのでした！</p>&mdash; す (@ktou) <a href="https://twitter.com/ktou/status/1329886484816482304?ref_src=twsrc%5Etfw">November 20, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

該当のコードを引用します。

```php
    /**
     * Magic method dispatcher to create custom SQL function calls
     *
     * @param string $name the SQL function name to construct
     * @param array $args list with up to 3 arguments, first one being an array with
     * parameters for the SQL function, the second one a list of types to bind to those
     * params, and the third one the return type of the function
     * @return \Cake\Database\Expression\FunctionExpression
     */
    public function __call(string $name, array $args): FunctionExpression
    {
        return new FunctionExpression($name, ...$args);
    }
```

なるほど…CakePHP4 にない関数が呼ばれた場合はマジックメソッドで処理されるんですね。そしてたまたま **group_concat** とスネークケースで書いていたので、MySQL と同じ関数だったので実行できていた、ということでした。

また、PR がマージされたら、 `groupConcat` とキャメルケースで呼び出すのが正しい実装となると思います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">で、Qiitaにまとめてくれた情報ですが、この情報はMySQL固有の話なので-&gt;group_concat()でOKです！関連情報として <a href="https://t.co/ScMFIoKfHX">https://t.co/ScMFIoKfHX</a> でMySQL以外でも同じAPIでGROUP_CONCAT()相当を使えるようなるのでマージされたら-&gt;groupConcat()の方が適切、という感じです！</p>&mdash; す (@ktou) <a href="https://twitter.com/ktou/status/1329889027151958016?ref_src=twsrc%5Etfw">November 20, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 今後
上記の PR がマージされたら、改めて動作検証した結果を反映します。

# 感謝
Twitterで軽い気持ちでわからないことを呟いたら、あれよあれよと言う間にすごい人たちがリプをくださり、検証してくださって、本当に感謝しかないです。
僕にとって、Twitterって世界はほんといつもいい刺激とインプットがもらえる最高の場所だし、最高な人がたくさんいて最高だなって語彙を失うレベルで日々みています。

僕も最高だなって思ってもらえるよう今後も活動していかねばって思わせていただいてます。
本当にいつも感謝です！ありがとうございますm(__)m