あっぽログ
← 記事一覧に戻る

SymfonyのRoutingコンポーネント入門:アノテーション・YAML・PHPでルートを定義する

Symfonyのルーティングとは

Symfonyのルーティングは、HTTPリクエストのURLをコントローラのアクションに紐づける仕組みです。Laravelと同様に強力なルーティング機能を持ちますが、Symfonyでは定義方法が複数用意されているのが特徴です。

  • PHP属性(Attribute)
  • YAML
  • XML
  • PHPファイル

本記事ではよく使われるPHP属性(Attribute)とYAMLを中心に、基本的なルーティングの使い方を解説します。


プロジェクトの準備

まずはSymfonyプロジェクトを作成します。

composer create-project symfony/skeleton my_project
cd my_project
composer require symfony/framework-bundle
composer require symfony/routing
composer require annotations

コントローラを生成します。

php bin/console make:controller ArticleController

PHP属性でルートを定義する(推奨)

Symfony 5.2以降では、PHP 8の#[Attribute]を使ってルートを定義するのが主流です。

<?php
// src/Controller/ArticleController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class ArticleController extends AbstractController
{
    #[Route('/articles', name: 'article_index', methods: ['GET'])]
    public function index(): Response
    {
        return new Response('<h1>記事一覧</h1>');
    }

    #[Route('/articles/{id}', name: 'article_show', methods: ['GET'])]
    public function show(int $id): Response
    {
        return new Response("<p>記事ID: {$id}</p>");
    }
}

ポイント

引数説明
第1引数URLパターン
nameルートの名前(一意である必要がある)
methods許可するHTTPメソッド

{id} のように波括弧で囲むとパラメータとして受け取れます。コントローラのメソッド引数名と一致させるだけで自動的にバインドされます。


YAMLでルートを定義する

config/routes.yaml に記述する方法です。設定ファイルでまとめて管理したい場合に便利です。

# config/routes.yaml

article_index:
    path: /articles
    controller: App\Controller\ArticleController::index
    methods: [GET]

article_show:
    path: /articles/{id}
    controller: App\Controller\ArticleController::show
    methods: [GET]

article_create:
    path: /articles
    controller: App\Controller\ArticleController::create
    methods: [POST]

パラメータに制約を加える

URLパラメータに正規表現で制約をつけることができます。たとえば {id} が数値のみを許可する場合は次のように書きます。

PHP属性での制約

#[Route('/articles/{id}', name: 'article_show', requirements: ['id' => '\d+'])]
public function show(int $id): Response
{
    return new Response("<p>記事ID: {$id}</p>");
}

YAMLでの制約

article_show:
    path: /articles/{id}
    controller: App\Controller\ArticleController::show
    requirements:
        id: '\d+'

/articles/abc のようなリクエストは404になり、/articles/123 だけが受け付けられます。


デフォルト値を設定する

パラメータにデフォルト値を持たせることもできます。

#[Route('/articles/{page}', name: 'article_list', defaults: ['page' => 1])]
public function list(int $page): Response
{
    return new Response("<p>{$page}ページ目の記事一覧</p>");
}

/articles にアクセスすると $page1 になり、/articles/3 にアクセスすると $page3 になります。


名前付きルートでURLを生成する

ルートに名前をつけておくと、テンプレートやコントローラでURLを動的に生成できます。ハードコードを避けられるため、URLを変更しても一箇所だけ直せばよくなります。

コントローラでの生成

use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class ArticleController extends AbstractController
{
    public function redirectToShow(int $id): Response
    {
        $url = $this->generateUrl('article_show', ['id' => $id]);
        return $this->redirect($url);
    }
}

Twigテンプレートでの生成

{# テンプレート内 #}
<a href="{{ path('article_show', { id: article.id }) }}">
    {{ article.title }}
</a>

path() は相対URL、url() は絶対URLを生成します。


ルート一覧を確認する

定義したルートの一覧はコンソールコマンドで確認できます。

php bin/console debug:router

出力例:

 Name             Method  Scheme  Host  Path
 article_index    GET     ANY     ANY   /articles
 article_show     GET     ANY     ANY   /articles/{id}
 article_create   POST    ANY     ANY   /articles

特定のルートの詳細を調べたいときは次のようにします。

php bin/console debug:router article_show

まとめ

Symfonyのルーティングの基本を整理します。

  • PHP属性(Attribute) でコントローラに直接ルートを定義するのが現在の主流
  • {パラメータ} で動的なURLセグメントを受け取れる
  • requirements で正規表現による制約が可能
  • defaults でデフォルト値を設定できる
  • 名前付きルートを使うと generateUrl()path() でURLを安全に生成できる
  • debug:router コマンドで定義済みルートを確認できる

LaravelのルーティングはPHPファイルに集約されますが、Symfonyでは属性やYAMLなどチームのスタイルに合わせた形式を選べるのが強みです。まずはPHP属性から試してみましょう。

← 記事一覧に戻る