【问题标题】:Auto detect internal/external development environment自动检测内部/外部开发环境
【发布时间】:2024-11-22 19:25:02
【问题描述】:

我们使用以下功能自动检测我们是在内部机器上还是在实时服务器上,然后为各种组件选择适当的配置:

function devIsLocal(){

    $res=false;

    $http_host=$_SERVER['HTTP_HOST'];

    if($http_host=='localhost')$res=true;
    if($http_host=='127.0.0.1')$res=true;
    if(substr($http_host,-4)=='.lan')$res=true;
    if(strpos($http_host, '.')===false)$res=true;

    return($res);

}

如您所见,它仅依赖于 HTTP_HOST 值。

当然,如果您在本地使用某种虚拟主机,例如 example.com,那么该功能就会被欺骗。

还有其他方法可以欺骗该功能吗?以及我们可以查看哪些其他变量/位置来确定我们在哪里?

【问题讨论】:

    标签: php development-environment production-environment autodiscovery


    【解决方案1】:

    在您的 Apache 虚拟主机配置中设置环境变量。 Zend 框架就是这样做的。

    请参阅ZF quick start guide 获取示例(“创建虚拟主机”部分。)

    在您的 httpd.conf 或 .htaccess 文件中,输入:

    SetEnv APPLICATION_ENV "development"
    

    然后在您的应用程序中,使用getenv 函数获取值:

    $environment = getenv("APPLICATION_ENV");
    if ($environment == "development")
    {
        // do development stuff
    }
    else if ($environment == "live")
    {
        // do live stuff
    }
    

    【讨论】:

    • 有时不允许编辑 httpd.conf。拥有一个包含表示环境的键值的 .htaccess 文件不是自动的。
    • @zaf - 您能否详细说明“拥有一个包含表示环境不是自动的键值的 .htaccess 文件”?我个人认为这是最优雅的解决方案,但主机可以限制您在 .htaccess 文件中可以执行的操作 - 这是您的意思吗?
    • @zaf 在 .htaccess 中设置变量与检查 HTTP_HOST 变量或将其添加到主配置(httpd.conf 等)一样自动
    • @Andy/Cez 我正在尝试在不修改应用程序所处环境的情况下找到一种方法。不像您的解决方案那样优雅但类似,我可以在应用程序配置中设置一个变量,但我想避免记住进行将应用程序从测试转移到生产所需的另一项修改(反之亦然)。 HTTP_HOST 是“自动的”,因为您无需执行任何操作。
    • @zaf 你总是在 *nix 服务器上吗?
    【解决方案2】:
    '127.0.0.1' == $_SERVER["REMOTE_ADDR"]
    

    这永远不会在您的实时系统上评估为TRUE。 :)

    【讨论】:

    • 如果您使用其面向公众的 IP 地址访问本地服务器,它也不会。
    • @toscho - 你必须明确,要么根据确切的解决方案定制你的答案,要么进一步解释这个概念 - 例如。 “为分配给服务器的所有 IP 地址添加额外检查。”然而,就我个人而言,我发现这是一个“高维护”的解决方案,特别是如果服务器的 IP 地址由 DHCP 和动态 DNS 管理 - 并不理想,但这是可能的,而且我已经在一些环境中看到了它。
    • 我使用 wamp。我想,由于 ipv6,代码不能按原样工作,这个概念确实工作完美。这是我使用的修改后的代码:if(($_SERVER["REMOTE_ADDR"] == '127.0.0.1') || ($_SERVER["REMOTE_ADDR"] == '::1')) {$environment = "development"; } else { $environment = "production"; }
    • 你必须小心 CLI 脚本试图用它来检测环境,如果本地脚本在本地发起 HTTP 请求,你的 REMOTE_ADDR 实际上将是 127.0.0.1。
    • ^^^ @philix 所说的。当REMOTE_ADDR 为空时,即通过命令行执行脚本时,这将不起作用。
    【解决方案3】:

    添加到Andy Shellam's answer..

    如果您使用 mod_vhost_alias,或者有多个域具有相同的(虚拟)文档根目录,您可以根据参数设置变量,例如

    SetEnvIf SERVER_ADDR x.x.x.x APPLICATION_ENV=development
    SetEnvIf HTTP_HOST abc.example.com APPLICATION_ENV=development
    

    【讨论】:

    • SetEnvIf 不使用正则表达式来评估 if 条件吗?如果是这样,您需要转义 . 不是吗?
    • @Lèsemajesté 诚然,文档显示了转义句点,但无论何时我使用 SetEnvIf,它似乎都可以正常工作
    • 我认为这是有道理的,因为. 可以匹配任何字符,包括句点,并且由于 IP 地址遵循固定格式,因此在这种情况下不会导致任何其他问题。跨度>
    【解决方案4】:

    创建并稍后查找仅存在于实时服务器文件系统上的文件。

    当然,您的环境应该尽可能相似;我的建议是这样的:在目录 /var/environment/ 中,有一个名为 {devel|test|qa|staging|live} 的文件,具体取决于您所在的服务器 - 然后只需检查文件名。

    当然,您需要将此文件从版本控制和您可能拥有的任何构建过程中排除。

    【讨论】:

    • 这是另一个途径。我没有创建文件(然后必须记住事实),而是考虑检查文件系统中的线索,例如主目录等,但有时生产服务器的文件系统与测试服务器相同。
    • 确实如此。我的意思是在 devel 上创建 /var/environment/devel,在 live 上创建 /var/environment/live 等。这些文件不需要有任何内容,除了区分环境之外,它们不得用于任何其他用途。编辑了我的答案以澄清。
    • 我最近的项目就是这样。我只是创建了一个名为 development.txt 的文件并在我的 config.php 文件中查找它。它简单、明确,不需要在项目目录之外进行任何更改。
    【解决方案5】:

    当然,如果你在本地使用了像example.com这样的虚拟主机,那么这个功能就会被欺骗。

    此外,如果主机不是本地主机但使用通配符或默认 vhost defn,并且用户将 IP 地址添加到本地主机文件中。

    我建议在包含路径上设置一个目录,该目录也存在于 live 中,但不会在那里复制 - 并且只需存储:

    function getEnv(){
      return 'Live';
    }
    

    function getEnv(){
      return 'Test';
    }
    

    如果两个 env 都在同一台服务器上 - 您仍然可以通过在 Apache config 或 .htaccess 中设置 include_path 来做到这一点。

    这还允许您分离潜在敏感的环境特定数据 - 例如数据库主机/密码和加密密钥。

    C.

    【讨论】:

    • 我们可以只检查一个目录是否存在,例如某个用户的主目录。有趣的想法。但有时专用的生产服务器文件系统布局会反映内部测试服务器。