Phoenix转发路由后如何让URL生成包含转发前缀?
解决Phoenix Forward路由下URL前缀丢失的问题
这个场景我之前在Phoenix项目开发中也碰到过,forward确实会导致子路由生成URL时自动丢失前缀,下面分享几个实用的解决办法:
方法一:手动传递script_name参数生成URL
当你使用forward时,Phoenix会自动把匹配到的前缀(这里是/child)添加到conn的script_name字段里。所以生成URL时,只要把这个参数传给路径helper就能得到正确结果:
在子控制器的action里:
def other(conn, _params) do # 生成带前缀的URL correct_url = Routes.page_path(conn, :other, script_name: conn.script_name) # 此时correct_url的值就是"/child/other" render(conn, "other.html", url: correct_url) end
如果是在模板中使用,直接在helper里传入参数即可:
<%= Routes.page_path(@conn, :other, script_name: @conn.script_name) %>
方法二:自定义Helper函数简化调用
上面的方法每次都要传参数有点繁琐,我们可以在子项目的Helper模块里封装一个自定义函数,自动处理前缀:
defmodule ChildWeb.Helpers do import Phoenix.Controller, only: [get_conn: 1] def child_page_path(conn_or_assigns, action) do conn = get_conn(conn_or_assigns) Routes.page_path(conn, action, script_name: conn.script_name) end end
之后在模板里直接调用这个自定义helper就行:
<%= child_page_path(@conn, :other) %>
方法三:替换Forward为挂载子Scope(更优雅的架构方式)
如果你的子路由不需要独立运行,只是作为主应用的一部分,其实可以不用forward,直接在主路由中挂载子路由的scope,这样路径前缀会被自动包含:
主Router修改为:
scope "/" do get "/", PageController, :index # 直接挂载子路由的scope,指定前缀和别名 scope "/child", ChildWeb do get "/other", PageController, :other end end
这种方式下,Routes.page_path(conn, :other)会自动生成/child/other,不需要额外处理,是最推荐的方案——除非你必须用forward来实现独立路由的转发(比如子应用可以单独启动)。
注意:如果子路由必须保持独立(比如可以单独作为一个Phoenix应用运行),那方法一或方法二更适合,既能保留子路由的独立性,又能正确生成带前缀的URL。
内容的提问来源于stack exchange,提问作者Sam Houston
相关产品推荐
相关产品推荐

