🎻
[Symfony] 1つのコントローラアクションに複数のURLを割り当てる
要件
-
Shopの一覧画面がもともとあり、都道府県で検索できる機能も付いている - そのURLは
/shopで、検索クエリは/shop?prefecture=aichiのようにURLパラメータで渡される - この、都道府県での検索結果の画面47パターンそれぞれに、
/shop/prefecture/aichiのような個別のURLを追加で割り当てたい
これを実現する方法を説明します。
解法
結論としては、ルーティングの記述をちょっと工夫するだけで簡単に実現できます。
このケースなら具体的には以下のようなコードになるでしょう。
class ShopController extends AbstractController
{
/**
* @Route("/shop/{prefecture?}", name="shop_index", requirements={"prefecture"="prefecture/[^/]+"})
*/
public function index(Request $request, ?string $prefecture)
{
$prefecture = str_replace('prefecture/', '', $prefecture);
if ($prefecture) {
$request->query->set('prefecture', $prefecture);
}
// ...
}
}
まず、ルーティングパラメータ {prefecture} を ? でnullableにすることで、「 / 以降に続きがあってもなくてもいい」状態にしています。(参考)
これで、もともとの /shop というURLでも問題なくアクセスできる状態を保てます。
さらに、requirementsオプション を使って {prefecture} のパターンを正規表現で規定しています。これをしておかないと、 /shop/{id} や /shop/{id}/edit などの他のURLも全部この index アクションにマッチしてしまうことになるので気をつけましょう。
あとは、ルーティングパラメータで受け取った都道府県名を表す文字列を prefecture クエリパラメータにセットしてあげることで、 /shop?prefecture=aichi のようなURLでアクセスしたときと同じ結果を返せるようにして完了です。
参考になれば幸いです🙂
Discussion