🎻
[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