路由基础 #

一、路由概述 #

1.1 什么是路由 #

路由是将HTTP请求映射到控制器动作的机制。Phoenix路由器负责匹配请求并调用相应的处理函数。

text
HTTP请求 → Router → Controller → Response

1.2 路由文件位置 #

elixir
defmodule HelloWeb.Router do
  use HelloWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", HelloWeb do
    pipe_through :browser
    get "/", PageController, :home
  end
end

二、基本路由定义 #

2.1 HTTP方法 #

Phoenix支持所有标准HTTP方法:

elixir
scope "/", HelloWeb do
  pipe_through :browser

  get "/users", UserController, :index
  post "/users", UserController, :create
  put "/users/:id", UserController, :update
  patch "/users/:id", UserController, :update
  delete "/users/:id", UserController, :delete
  options "/users", UserController, :options
  head "/users", UserController, :head
end

2.2 路由结构 #

elixir
get "/path", ControllerModule, :action_name
部分 说明
get HTTP方法
“/path” URL路径
ControllerModule 控制器模块
:action_name 动作函数名

2.3 路由示例 #

elixir
defmodule HelloWeb.Router do
  use HelloWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :protect_from_forgery
  end

  scope "/", HelloWeb do
    pipe_through :browser

    get "/", PageController, :home
    get "/about", PageController, :about
    get "/contact", PageController, :contact
  end
end

三、资源路由 #

3.1 RESTful资源 #

elixir
scope "/", HelloWeb do
  pipe_through :browser

  resources "/users", UserController
end

这会生成以下路由:

HTTP方法 路径 控制器动作 说明
GET /users UserController.index 列表
GET /users/new UserController.new 新建表单
POST /users UserController.create 创建
GET /users/:id UserController.show 详情
GET /users/:id/edit UserController.edit 编辑表单
PUT /users/:id UserController.update 更新
PATCH /users/:id UserController.update 更新
DELETE /users/:id UserController.delete 删除

3.2 限制资源动作 #

elixir
resources "/users", UserController, only: [:index, :show]

resources "/posts", PostController, except: [:delete]

resources "/comments", CommentController, only: [:create, :update, :delete]

3.3 资源选项 #

elixir
resources "/posts", PostController do
  resources "/comments", CommentController
end

resources "/photos", PhotoController, param: "slug"

四、作用域 #

4.1 基本作用域 #

elixir
scope "/", HelloWeb do
  pipe_through :browser

  get "/", PageController, :home
end

4.2 带路径前缀的作用域 #

elixir
scope "/admin", HelloWeb do
  pipe_through :browser

  get "/dashboard", AdminController, :dashboard
  resources "/users", Admin.UserController
end

生成的路由:

路径 控制器
/admin/dashboard HelloWeb.AdminController
/admin/users HelloWeb.Admin.UserController

4.3 带模块前缀的作用域 #

elixir
scope "/api", HelloWeb.Api, as: :api do
  pipe_through :api

  resources "/users", UserController
end

生成的路径辅助函数:

elixir
~p"/api/users"
api_user_path(conn, :index)

4.4 嵌套作用域 #

elixir
scope "/admin", HelloWeb.Admin, as: :admin do
  pipe_through [:browser, :admin]

  get "/", DashboardController, :index

  scope "/users" do
    resources "/", UserController, only: [:index, :show]
  end
end

五、管道 #

5.1 管道定义 #

elixir
pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end

pipeline :api do
  plug :accepts, ["json"]
end

5.2 使用管道 #

elixir
scope "/", HelloWeb do
  pipe_through :browser

  get "/", PageController, :home
end

scope "/api", HelloWeb do
  pipe_through :api

  resources "/users", UserController
end

5.3 多个管道 #

elixir
scope "/admin", HelloWeb.Admin do
  pipe_through [:browser, :admin_auth]

  resources "/users", UserController
end

六、路径辅助函数 #

6.1 自动生成的辅助函数 #

elixir
resources "/users", UserController

生成以下辅助函数:

elixir
user_path(conn, :index)
user_path(conn, :show, user.id)
user_path(conn, :new)
user_path(conn, :create)
user_path(conn, :edit, user.id)
user_path(conn, :update, user.id)
user_path(conn, :delete, user.id)

6.2 使用~p宏 #

elixir
~p"/users"
~p"/users/#{user.id}"
~p"/users/#{user.id}/edit"

6.3 URL生成 #

elixir
user_url(conn, :index)
user_url(conn, :show, user.id)

Routes.user_path(conn, :index)
Routes.user_url(conn, :index)

七、路由约束 #

7.1 参数约束 #

elixir
get "/posts/:id", PostController, :show, assigns: %{id: ~r/^\d+$/}

7.2 自定义约束 #

elixir
defmodule HelloWeb.Plugs.AdminConstraint do
  def init(opts), do: opts

  def call(conn, _opts) do
    if admin?(conn) do
      conn
    else
      conn
      |> Plug.Conn.send_resp(403, "Forbidden")
      |> Plug.Conn.halt()
    end
  end

  defp admin?(conn) do
    conn.assigns[:current_user].role == "admin"
  end
end

八、转发 #

8.1 转发到其他模块 #

elixir
scope "/", HelloWeb do
  pipe_through :browser

  forward "/health", HealthCheck
  forward "/metrics", MetricsExporter
end

8.2 转发示例 #

elixir
defmodule HelloWeb.HealthCheck do
  def init(opts), do: opts

  def call(conn, _opts) do
    conn
    |> Plug.Conn.put_resp_content_type("text/plain")
    |> Plug.Conn.send_resp(200, "OK")
  end
end

九、路由查看 #

9.1 查看所有路由 #

bash
mix phx.routes

输出:

text
page_path  GET  /               HelloWeb.PageController :home
user_path  GET  /users          HelloWeb.UserController :index
user_path  GET  /users/:id      HelloWeb.UserController :show
user_path  GET  /users/new      HelloWeb.UserController :new
user_path  POST /users          HelloWeb.UserController :create

9.2 过滤路由 #

bash
mix phx.routes HelloWeb.Router user

十、路由最佳实践 #

10.1 组织路由 #

elixir
defmodule HelloWeb.Router do
  use HelloWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :protect_from_forgery
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", HelloWeb do
    pipe_through :browser

    get "/", PageController, :home
    resources "/posts", PostController
  end

  scope "/api", HelloWeb.Api, as: :api do
    pipe_through :api

    resources "/users", UserController
    resources "/posts", PostController
  end
end

10.2 命名约定 #

elixir
resources "/users", UserController
resources "/posts", PostController
resources "/comments", CommentController

scope "/admin", HelloWeb.Admin, as: :admin do
  resources "/users", UserController
end

十一、总结 #

11.1 核心概念 #

概念 说明
get/post/put/delete HTTP方法路由
resources RESTful资源路由
scope 路由作用域
pipeline 请求处理管道
pipe_through 应用管道
~p 路径宏

11.2 下一步 #

现在你已经了解了路由基础,接下来让我们学习 路由参数,深入了解参数处理!

最后更新:2026-03-28