如何在PHP中使用环境变量的方法

1,087 阅读4分钟

环境变量是配置PHP应用程序的一个很好的方法,因为它们把应用程序的设置放在代码之外。通过这样做,可以更容易地防止安全凭证的暴露,维护应用程序,以及在多个环境中使用应用程序。

在本教程中,你将了解到在PHP应用程序中设置和检索环境变量的许多方法中的一些。这样,你的应用程序就可以访问它需要的所有信息,如API密钥、上传的文件、查询字符串和表单数据。

如何在PHP中访问环境变量

使用PHP的Superglobals

在PHP中访问环境变量的最常见的方式之一是通过使用Superglobals。这些是内置的、预定义的变量,在所有作用域中都可用。由PHP运行时初始化,它们以一种(大部分)逻辑和有效的方式组织PHP的环境信息,因此只需要查阅一个数组就可以检索到所需的信息。

例如,$_SERVER 包含请求头、路径和脚本位置,$_SESSION 包含会话变量,$_POST 包含用 HTTP POST 方法调用时传递给当前脚本的变量。

也就是说,有一些事情是需要注意的:

  • 首先,根据 variables_order 指令的设置方式,一个或多个超全局数组可能为空。如果你的应用程序依赖于某个特定的Superglobal被填充,那么检查这一点就很重要。
  • 其次$_SERVER$_ENV (包含从 PHP 解析器运行环境中导入的变量)中包含的变量可能会相互重叠,这取决于脚本的上下文。如果你希望这些键在所有的Superglobals中都是唯一的,这可能会令人困惑。

SAPI/CGI和CLI环境之间的差异

除了variables_order 指令外,环境也对Superglobals中的信息设置起到了一定作用。具体来说,如果你的应用程序是使用CGI、FastCGI或SAPI运行的,那么$_SERVER ,除了正常的变量外,还将被填充环境变量。或者,如果你使用的是PHP CLI,那么只有$_SERVER 会被设置。

使用 getenv()

除了使用PHP的Superglobals之外,还可以使用getenv()来检索环境变量。如果调用该函数时没有参数,那么它会返回所有可用的环境变量。然而,如果传递了一个参数,就会返回具有该名称的环境变量的值。

你可以在下面看到它的使用例子:

echo getenv('SHELL');
foreach (getenv() as $key => $value) {
    echo $key . ' - ' . $value;
}

与PHP的Superglobals一样,使用这个函数也有一个问题。引述该函数的文档:

如果 PHP 在一个 SAPI 中运行,如 Fast CGI,这个函数将总是返回 SAPI 设置的环境变量的值,即使putenv()被用来设置同名的本地环境变量。使用local_only 参数来返回本地设置的环境变量的值。

请注意,getenv() 不是线程安全的。

使用apache_getenv()

如果你使用Apache作为你的网络服务器,那么你有一个额外的函数可以使用:apache_getenv()。这个函数可以检索在Apache进程中设置的环境变量。你可以在下面看到一个使用它的例子:

echo apache_getenv('NAME');

不要隐含地相信环境变量!

需要强调的是--无论数据来自哪里,无论是来自PHP的某个超级球体、Web服务器配置,还是操作环境--都不要隐含地相信它环境变量应该被过滤和验证,就像任何其他应用的外部数据一样。

如何设置环境变量

除了阅读环境变量,知道如何设置它们也很有帮助,这样,你就知道如何在必要时改变它们。在下面的例子中,我们要把环境变量NAME ,设置为 "Robert Smith",英国摇滚乐队The Cure的主唱。

在环境中设置它们

在启动Web服务器或执行PHP脚本之前,可以在当前环境中设置环境变量。

如果你想更深入地了解设置环境变量,Dominik Kundel已经写了一篇详细的博文

UNIX、Linux和macOS

如果你使用的是这三个操作系统中的一个,或者像BSD这样的变种,那么有三个范围,你可以设置环境变量:

  • 对当前环境(会话)和所有子会话可用。
  • 只对当前会话可用。
  • 只对一个特定的进程可用。

你可以在下面的代码中看到这三种情况的例子:

# Available to the current environment (session) and all child sessions.
export NAME="Robert Smith"

# Available only to the current session.
NAME="Robert Smith"

# Available only to a specific process.
NAME="Robert Smith" php script.php

微软视窗

设置环境变量在Microsoft Windows中有些不同。你可以在控制面板上设置它们,也可以在命令提示符或PowerShell控制台中设置它们。下面有后两者的例子:

# Set NAME in the Windows Command Prompt
set NAME="Robert Smith"

# Set NAME in the Windows PowerShell console
$Env:NAME = "Robert Smith"

使用Docker

如果你使用Docker,你可以使用ENV 命令在Docker文件中设置环境变量,如下面的例子:

ENV NAME "Robert Smith"

如果你使用Docker Compose构建一个多容器配置,你可以在docker-compose.yml中使用环境键设置环境变量,如下面的例子:

environment:
  - NAME="Robert Smith"

在使用Docker时,还有其他一些设置环境变量的方法,你可以在Docker文档Docker Compose文档中阅读。

使用putenv()

使用这个函数,你可以在当前请求中设置一个环境变量的值--以及取消设置它。在下一个请求中,如果该变量在当前请求之外设置,将返回其原始值。

以这种方式设置的变量对该脚本调用的进程也是可用的,并且只有通过调用getenv()

你可以在下面的代码中看到这两个函数的一个例子:

// Set the environment variable, NAME.
putenv('NAME="Robert Smith"');

// Retrieve the environment variable, NAME.
echo getenv('NAME');

// Unset the environment variable, NAME.
putenv('NAME');

请注意,putenv() 不是线程安全的。

使用apache_setenv() 与`putenv()`相似的是`apache_setenv()`。这个函数设置一个Apache进程特定的环境变量。当然,这个函数和它的补码只有在使用Apache时才可用。你可以在下面看到一个使用它的例子:

apache_setenv('NAME', 'Robert Smith');
echo apache_getenv('NAME');

在NGINX配置中设置环境变量

如果你使用NGINX作为你的网络服务器,你可以使用 fastcgi_param 指令来设置一个环境变量。该指令需要一个区分大小写的名称和值,如果包含空格,必须加引号

fastcgi_param NAME "Robert Smith";

这些变量可以通过getenv() ,以及$_ENV$_SERVER 超级全局数组中获得。

在Apache配置中设置环境变量

如果你使用Apache作为你的网络服务器,那么你可以使用SetEnv 指令来设置环境变量。该指令可以在Apache的主服务器配置、虚拟主机配置、目录配置或*.htaccess*文件中使用。

该指令需要一个区分大小写的名称和值,如果它包含空格,则必须加引号。如果没有提供值,该变量将被初始化为一个空字符串:

SetEnv NAME "Robert Smith"

与在NGINX中使用fastcgi_param 不同,在Apache中使用SetEnv (或相关函数之一)设置的环境变量只在$_SERVER 超级全局中可用。

使用.env文件

虽然上述每种方式都有其优点,但也有一些缺点需要记住:

  • 根据项目的复杂性,它们在长期的维护过程中可能具有挑战性。
  • 没有必要的环境变量的中央清单,也没有关于特定变量作用的细节,更没有它们允许的数据类型。

另一种方法是使用dotenv文件,以事实上的文件名命名:.env,这种方法近年来在PHP中获得了很大的发展。这些文件是纯文本文件,以键/值对列表的形式定义了应用程序工作所需的环境变量。

你可以看到下面的一个例子:

NAME="Robert Smith"

假设上面的例子是我们项目的*.env文件,我们可以使用vlucas/phpdotenv这样的包,它默认读取.env*文件,并将其中定义的变量添加到$_ENV$_SERVER 超级球体中。

要做到这一点,我们首先要通过运行下面的命令将该包安装为应用程序的依赖项:

composer require vlucas/phpdotenv

然后,我们将使用该包来加载环境变量,如下面的例子:

<?php

declare(strict_types=1);

require_once('vendor/autoload.php');

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

echo $_ENV['NAME'] . "\n";
echo $_SERVER['NAME'] . "\n";
  • 使用safeLoad() ,而不是load() ,以避免在没有找到.env 时抛出一个异常。
  • 将一个文件路径作为第二个参数传给createImmutable() ,以使用.env 以外的文件。

关于.env文件安全的说明

重要的是要意识到*.env*文件中的敏感数据不能存储在版本控制之下!如果发生这种情况,所有的安全性都会受到影响。

如果发生这种情况,使用dotenv文件的所有安全优势都会丧失。这就是为什么通常要把它们排除在版本控制之外,例如在使用Git时,把*.env*和文件名的变化添加到项目的.gitignore文件中。

这就是如何在PHP中使用环境变量的方法

我希望这篇文章能帮助你理解如何在你的PHP项目中使用环境变量。你还有其他使用环境变量的方法吗?我很想知道!