我已经开始自学Phoenix Framework并且他们的文档非常好。然而,在指定可选路由参数时,我遇到了绊脚石。 Phoenix Framework Routing Documentation没有提到这个特征,所以我假设责任落在了开发者身上以提出解决方案。
我将列出我的用例:
/page/test
网站,自定义Plug然后实施一些代码以查找或为该连接分配locale
。:locale
参数,因此我的管道中的行使用默认值plug HelloPhoenix.Plugs.Locale, "en"
。/fr/page/test
处的网站,并在管道中执行相同的代码,除了路由中存在:locale
参数的时间,自定义插件(HelloPhoenix.Plugs.Locale
)。 现在从路由的角度来看,如果我不能指定:locale
参数是可选的,我最终会增加两倍的路由数量,例如:
scope "/", HelloPhoenix do
use_pipeline :browser
plug HelloPhoenix.Plugs.Locale, "en"
# Route without locale
get "/page/:slug", PageController, :show
# Route with locale
get "/:locale/page/:slug", PageController, :show
end
正如您所知,如果没有指定可选路由参数的能力,这很快就会变得非常艰巨和重复。
不,我确实有一个解决方法,我将在答案中发布,但我不确定它是否正确,以及(b)最简单的解决方案,因为我' Erlang,Elixir和Phoenix的新手(我来自Ruby和PHP OOP的背景)。
答案 0 :(得分:7)
您可以使用简单的插件:
defmodule MyApp.SetLocale do
@locales ~w{en fr}
def init(opts), do: opts
def call(conn, _opts) do
case conn.path_info do
[locale | rest] when locale in @locales ->
%{conn | path_info: rest}
|> Plug.Conn.assign(:locale, locale)
_ -> Plug.Conn.assign(conn, :locale, "en")
end
end
end
然后将此插头放在endpoint.ex
中的路由器之前 plug MyApp.SetLocale
plug MyApp.Router
end
通过这种方式,您可以确信在您到达路由器之前已经设置了区域设置。您根本不需要在路由器中提及它。
如果您输入的区域设置不在@locales
中,则此技术将为404。
答案 1 :(得分:2)
正如我在问题中所提到的,我提出了一个适用于我的解决方案,但我不确定它是正确的还是最简单的解决方案(特别是如果路由变得更复杂)......
我的解决方案使用Enum.each
循环遍历前缀列表,然后只需要指定一次路由。这似乎有效:
scope "/", HelloPhoenix do
use_pipeline :browser
plug HelloPhoenix.Plugs.Locale, "en"
# Loop over list containing prefix :locale and no prefix.
Enum.each ["/:locale", "/"], fn prefix ->
# No need to duplicate routes
get prefix <> "/page/:slug", PageController, :show
end
end