CodeIgniter4のルーティングでのプレイスホルダー (:any) について

この記事は CodeIgniter Advent Calendar 2022 - Qiita の11日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

動作確認環境

  • CodeIgniter 4.3 ブランチ (8e795334c1d3adc5646e2bb726b28fab9376b3c4)

プレイスホルダーとは?

ルーティングでのプレイスホルダーとは、例えば、以下のルーティング定義での (:any) のことです。

$routes->get('product/(:any)', 'Product::find/$1');

プレイスホルダーは正規表現を表す記号です。内部的に正規表現に変換されます。

CodeIgniter4では以下があります。

  • (:any): 複数のURIセグメントにマッチする
  • (:segment): 1つのURIセグメントにマッチする
  • (:num): 1つの数字のみのURIセグメントにマッチする
  • (:alpha): 1つのアルファベットのみのURIセグメントにマッチする
  • (:alphanum): 1つのアルファベットと数字のみのURIセグメントにマッチする
  • (:hash): (:segment) と同じ

ちなみに、CodeIgniter3では (:any)(:num) がありました。

CI3の (:any) はCI4の (:any) ではない

同じ名前なので、CodeIgniter3の (:any) とCodeIgniter4の (:any) が同じだと思っていたのですが、違いました。

CodeIgniter3の (:any) はCodeIgniter4では (:segment) です。

CodeIgniter4の (:any) は新しく追加された機能でした。

CI4の (:any) の動作

例えば、以下のルートを定義します。

$routes->get('product/(:any)', 'Product::find/$1');

ここで、

http://localhost:8080/product/category/filter1/filter2

にアクセスすると、(:any) は複数のURIセグメントにマッチするので、 product/category/filter1/filter2product/(:any) にマッチします。

よって、このルートにマッチするので、Product::find() メソッドが呼び出されます。

では、ここで引数はどうなるでしょうか?

(:any) に対応するURIは category/filter1/filter2 ですので、第1引数に category/filter1/filter2 が渡されるかと思っていたのですが、違いました。

Productコントローラを作成して確認してみましょう。

<?php

namespace App\Controllers;

use App\Controllers\BaseController;

class Product extends BaseController
{
    public function find(...$params)
    {
        dd($params);
    }
}

結果は以下のようになりました。

$params array (3)
    ⇄0 => string (8) "category"
    ⇄1 => string (7) "filter1"
    ⇄2 => string (7) "filter2"
⧉ Called from .../app/Controllers/Product.php:11 [dd()]

つまり、引数はURIセグメントの数だけ渡されます。

結果として、(:any) を使った場合は、引数の数がアクセスされるURIに応じて変わります。

つまり、以下のような定義をすると、(:num) に対応する引数が何番目の引数になるかはわかりません。

$routes->get('product/(:any)/(:num)', 'Product::find/$1/$2');

このような使い方はややこしいだけなので、すべきではありません。

まとめ

  • CodeIgniter4のルーティングでの (:any) は複数のURIセグメントにマッチします。
  • CodeIgniter4の (:any) はCodeIgniter3の (:any) とは動作が異なります。
  • (:any) が複数のURIセグメントにマッチした場合でも、コントローラのメソッドに渡される引数はURIセグメントごとになります。
  • (:any) の後にさらにプレースホルダーを記載することはやめましょう。

この記事は CodeIgniter Advent Calendar 2022 - Qiita の11日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。

関連

参考

Date: 2022/12/11

Tags: codeigniter, codeigniter4