🐕

CakePHP4.3でコントローラーのアクションの引数にstring型以外を指定できるようになっていた件

2021/12/14に公開

この記事は コネヒト Advent Calendar 2021 14日目の記事です。
最近は業務でCakePHPのバージョンアップ作業を行っており、その中で気づいた小ネタについてまとめてみます。

CakePHP4系のCookbookより

https://book.cakephp.org/4/ja/appendices/4-3-migration-guide.html
CakePHP4.3移行ガイド中に以下のような記述があります。

  • コントローラでは、アクションパラメータに float, int, bool, array のいずれかの型宣言をサポートするようになりました。 ブール型で渡されるパラメータは、 0 か 1 のどちらかでなければなりません。

具体的には以下のように、コントローラー内viewアクションの引数にint型を指定したりできるようになりました。[1]

class ArticlesController extends AppController
{
    public function view(int $id)
    {
        // 何かしらの処理
    }
}

今まではどうだったのか?

CakePHP4.2までは引数にstring型しか指定できませんでした。

$routes->connect(
    '/articles/{id}',
    ['controller' => 'Articles', 'action' => 'view']
)
->setPatterns(['id' => '\d+'])
->setPass(['id']);

このようにルーティング時点でバリデーションを行い、idは絶対に数値だ!となっていても、以下のようにstring型しか指定できませんでした。
そのため、処理の中で$idint型として扱いたい場合は、(int)$idのようにキャストする必要がありました。

class ArticlesController extends AppController
{
    public function view(string $id)
    {
        // 何かしらの処理
        // $idをint型で扱いたい場合は(int)$idのようにキャストが必要
    }
}

あれ、以前のバージョンでもstring型以外を指定できるよ?

実はCakePHP3以前では、string型以外を指定してもエラーにはなりません。これは、暗黙の型変換が行われるためです。
CakePHP4以降は、declare(strict_types=1);宣言されるようになったため、厳密な型チェックが行われ、string型以外ではエラーになります。

ちなみに、自分も誤解していたのですが、declare(strict_types=1);が有効なのは、宣言されたファイルから行われる関数呼び出しに対して[2]です。(宣言されたファイル内の関数に対してではありません!)
CakePHP4以降は、フレームワーク側全体にdeclare(strict_types=1);宣言されているため、コントローラーのアクションの引数では必ず厳密な型チェックが行われます。

おわりに

実はCakePHP4.3へのバージョンアップはまだまだ先なのですが、気づいたのでまとめてみました。いつかCakePHP4.3にできたら、この機能を活用してみたいと思います〜。

脚注
  1. 関連するCakePHPのコードは以下
    ここで、指定された型に応じて変換しています
    https://github.com/cakephp/cakephp/blob/4.x/src/Controller/ControllerFactory.php#L248-L271 ↩︎

  2. 以下が参考になります
    https://www.php.net/manual/ja/language.types.declarations.php#language.types.declarations.strict
    https://qiita.com/Hiraku/items/734f0666ab3d34c52efa ↩︎

Discussion