Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir Phoenix在运行时未加载环境变量_Elixir_Phoenix Framework_Elixir Mix - Fatal编程技术网

Elixir Phoenix在运行时未加载环境变量

Elixir Phoenix在运行时未加载环境变量,elixir,phoenix-framework,elixir-mix,Elixir,Phoenix Framework,Elixir Mix,在启动phoenix服务器时,我正在尝试从mac加载一个API密钥作为系统环境。我做错了什么?以下是我的步骤: 在我的mac终端上: export API_NOTIFICATION_KEY=1234 在我的config.exs中 config :app, App.Notifications, notification_api_key: {:system, "API_NOTIFICATION_KEY"} 在我使用它的模块中 @api_notification_key Application

在启动phoenix服务器时,我正在尝试从mac加载一个API密钥作为系统环境。我做错了什么?以下是我的步骤:

  • 在我的mac终端上:

    export API_NOTIFICATION_KEY=1234
    
  • 在我的config.exs中

    config :app, App.Notifications,
    notification_api_key: {:system, "API_NOTIFICATION_KEY"}
    
  • 在我使用它的模块中

    @api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]
    
  • 启动我的凤凰服务器

    mix phx.server
    

  • 然后,当我尝试进行API调用时,它显示为nil。是否缺少使其正确加载的步骤?

    编译期间会对属性进行评估,因此:

    @api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]
    
    将在编译时设置其值。我认为这不是您想要的,因此您最好使用函数:

    defp api_notification_key() do
      case Application.get_env(:test, App.Notifications)[:notification_api_key] do
        {:system, var_name} -> System.get_env(var_name)
        value -> value
      end
    end
    

    当我使用您的配置时,请尝试通过以下方式访问控制器中的密钥:

    Application.get_env(:app, App.Notifications)[:notification_api_key]
    
    我得到:

    {:system, "API_NOTIFICATION_KEY"}
    
    所以phoenix没有查找env变量。另一方面,如果我在配置中手动设置键,如下所示:

    config :app, App.Notifications,
        notification_api_key: 1234
    
    然后我在控制器中得到
    1234
    。我读到一篇文章,说用
    {:system,“ENV_VAR”}
    读取环境变量在某个时候会被弃用,我在文档中没有看到任何关于
    :system
    的提及。我使用的是
    phoenix 1.4.6

    根据,您可以在
    endpoint.ex
    中定义
    init/2
    函数,该函数将在运行时调用——就在phoenix应用程序启动之前——这意味着您可以在运行时使用
    System.get_env/1
    直接查找环境变量。
    init/2
    功能的描述如下:

    动态配置

    用于动态配置端点,例如从 环境变量或配置文件,Phoenix调用 端点上的init/2回调,首先传递:supervisor atom 参数和端点配置作为第二个参数

    我举了一个例子:

      def init(:supervisor, config) do
        #IO.inspect config, label: "config"
        #IO.inspect Application.get_all_env(:app1), label: "all"
    
        Application.put_env(:app1, :notification_api_key, 
            System.get_env("API_NOTIFICATION_KEY"),
            persistent: true
        )
    
        {:ok, config}
      end
    
    然后在我的控制器中:

    key = Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect key, label: "key" 
    
    @attr Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect(
      App1Web.Endpoint.config(:notification_api_key, :not_set), 
      label: "config"
    )
    
    在服务器窗口中,我看到:

    key: 1234
    
    您还应该认识到,设置模块属性发生在编译时,因此此行:

    @api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]
    
    检索编译应用程序的系统的env变量

    我还尝试在控制器中设置模块属性:

    key = Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect key, label: "key" 
    
    @attr Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect(
      App1Web.Endpoint.config(:notification_api_key, :not_set), 
      label: "config"
    )
    
    和上面在endpoint.ex中定义的
    init/2
    ,在我的控制器@attr中是nil——正如预期的那样。这是因为在编译时,
    init/2
    尚未被调用,因此没有设置
    :notification\u api\u key
    的值

    对我来说,调用
    Application.put_env()
    init/2
    中是不对的:

      def init(:supervisor, config) do
    
        Application.put_env(:app1, :notification_api_key, 
            System.get_env("API_NOTIFICATION_KEY"),
            persistent: true
        )
    
        {:ok, config}
      end
    
    我想我应该做点什么来配置。下面是另一个例子:

      def init(:supervisor, config) do
    
        IO.inspect config, label: "config"
    
        key = System.get_env("API_NOTIFICATION_KEY")
        new_config = Keyword.put_new(config, :notification_api_key, key)
    
        IO.inspect new_config, label: "inside init/2: new_config"
    
        {:ok, new_config}
      end
    
    然后在我的控制器中:

    key = Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect key, label: "key" 
    
    @attr Application.get_env(
            :app1, App1.Notifications 
          )[:notification_api_key]
    
    IO.inspect(
      App1Web.Endpoint.config(:notification_api_key, :not_set), 
      label: "config"
    )
    
    在“我的服务器”窗口中,我看到:

    config: "1234"
    

    因此,这也是可行的。

    属性在编译期间进行评估——如果op在与编译应用程序的系统不同的系统上运行应用程序,这难道不会导致问题吗?换句话说,op声称env变量是在编译时之前设置的,然后应用程序被编译。因此,在编译时烘焙到应用程序中的env变量应该在运行时可用,但op得到
    nil
    。即使op在与编译应用程序的系统不同的系统上运行应用程序,op仍应获得
    1234
    作为环境变量的值……。只是
    1234
    的值不会是运行应用程序的系统上的env变量的值。嗯,我正准备写一个这样的函数,我又看了一遍你的答案。我搜索了hi和lo,以及类似这样的文章:让它看起来像凤凰有一个像你一样的本地功能。我找不到任何地方表明,当您在配置中使用系统元组时,您需要在
    键的
    值中编写自己的函数来检测
    :system
    。我读到的所有内容都让人觉得,如果您使用系统元组,那么某些应用程序将……在运行时自动为您查找env变量。我最后得出结论,Application.get_env()
    只是一个愚蠢的查找函数,它不关心是否使用
    :system
    或其他任何东西作为键的值,而像phoenix这样的应用程序必须处理:system——如果它愿意的话。