【问题标题】:Optional routing parameters in Phoenix FrameworkPhoenix 框架中的可选路由参数
【发布时间】:2016-07-01 11:59:07
【问题描述】:

我已经开始自学Phoenix Framework,他们的文档非常好。然而,在指定可选路由参数时,我遇到了一个绊脚石。 Phoenix Framework Routing Documentation 没有提到这是一项功能,所以我假设开发人员有责任提出解决方案。

我将列出我的用例:

  1. 用户访问位于/page/test 的站点,自定义Plug 然后实现一些代码来查找或分配locale 到连接。
  2. 由于路径中没有:locale参数,所以按照我的管道中的那一行使用默认值,即plug HelloPhoenix.Plugs.Locale, "en"
  3. 用户访问/fr/page/test 的站点,并且在管道中执行相同的代码,除了时间因为:locale 参数存在于路由中,自定义Plug (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

如您所知,如果无法指定可选的路由参数,这很快就会变得非常繁重和重复。

不,我确实有一个解决方法,我将在答案中发布,但我不确定它是否 (a) 正确,以及 (b) 最简单的解决方案,因为我我是 Erlang、Elixir 和 Phoenix 的新手(我来自 Ruby 和 PHP OOP 的背景)。

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    你可以有一个简单的插件,比如:

    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。

    【讨论】:

    • 很好,谢谢@Gazler,这对我有很大帮助。我已经对其进行了修改,因此默认语言环境是一个模块变量,它重定向到删除了语言环境参数的路径。
    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多