配置

每个框架都使用配置文件来定义许多参数和初始设置。CodeIgniter 配置文件定义简单的类,其中所需的设置是公共属性。

与许多其他框架不同,CodeIgniter 可配置项不包含在单个文件中。相反,每个需要可配置项的类都将有一个与使用它的类同名的配置文件。您将在 app/Config 文件夹中找到应用程序配置文件。

使用配置文件

获取配置对象

您可以通过几种不同的方式访问类的配置文件。

new 关键字

通过使用 new 关键字创建实例

<?php

// Creating new configuration object by hand
$config = new \Config\Pager();

config()

通过使用 config() 函数

<?php

// Get shared instance with config function
$config = config('Pager');

// Access config class with namespace
$config = config('Config\\Pager');
$config = config(\Config\Pager::class);

// Creating a new object with config function
$config = config('Pager', false);

如果没有提供命名空间,它将首先在 app/Config 文件夹中查找文件,如果未找到,则在所有定义的命名空间中的 Config 文件夹中查找。

所有与 CodeIgniter 一起提供的配置文件都使用 Config 命名空间。在您的应用程序中使用此命名空间将提供最佳性能,因为它确切地知道在哪里查找文件。

注意

在 v4.4.0 之前,config() 在存在具有相同短名称的类时在 app/Config/ 中查找文件,即使您指定了完全限定的类名,例如 config(\Acme\Blog\Config\Blog::class)。此行为已在 v4.4.0 中修复,并返回指定的实例。

获取配置属性

所有配置对象属性都是公开的,因此您可以像访问任何其他属性一样访问设置。

<?php

$config = config('Pager');
// Access settings as object properties
$pageSize = $config->perPage;

创建配置文件

当您需要一个新的配置时,首先您需要在您想要的位置创建一个新文件。默认文件位置(大多数情况下推荐)是 **app/Config**。

您可以通过使用不同的命名空间将配置文件放在任何 **Config** 文件夹中。

该类应该使用适当的命名空间,并且应该扩展 CodeIgniter\Config\BaseConfig 以确保它可以接收特定于环境的设置。

定义类并用表示您的设置的公共属性填充它。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class CustomClass extends BaseConfig
{
    public $siteName  = 'My Great Site';
    public $siteEmail = '[email protected]';
    // ...
}

环境变量

如今,应用程序设置的最佳实践之一是使用环境变量。这样做的一大原因是环境变量易于在部署之间更改,而无需更改任何代码。配置在部署之间可能会发生很大变化,但代码不会。例如,多个环境(例如开发人员的本地机器和生产服务器)通常需要针对每个特定设置的不同配置值。

环境变量还应用于任何私密信息,例如密码、API 密钥或其他敏感数据。

Dotenv 文件

CodeIgniter 通过使用“dotenv”文件使设置环境变量变得简单且轻松。该术语来自文件名,该文件名以点开头,然后是“env”。

创建 Dotenv 文件

CodeIgniter 期望 **.env** 文件位于项目的根目录,与 **app** 目录并列。CodeIgniter 分发了一个模板文件,该文件位于项目的根目录,名为 **env**(注意,开头没有点 (.)?)。

它包含项目可能使用的许多变量,这些变量已被分配了空值、虚拟值或默认值。您可以通过将模板重命名为 **.env** 或通过制作名为 **.env** 的副本,将此文件用作应用程序的起点。

警告

确保 **.env** 文件未被您的版本控制系统跟踪。对于 *git*,这意味着将其添加到 **.gitignore** 中。如果未这样做,可能会导致敏感凭据暴露给公众。

设置变量

设置存储在 **.env** 文件中,以简单的键值对形式存储,键值对之间用等号分隔。

S3_BUCKET = dotenv
SECRET_KEY = super_secret_key
CI_ENVIRONMENT = development

当您的应用程序运行时,**.env** 文件将自动加载,并将变量放入环境中。如果环境中已存在该变量,则不会被覆盖。

获取变量

可以使用以下任何一种方法访问加载的环境变量:getenv()$_SERVER$_ENV

<?php

$s3_bucket = getenv('S3_BUCKET');
$s3_bucket = $_ENV['S3_BUCKET'];
$s3_bucket = $_SERVER['S3_BUCKET'];

警告

请注意,来自 **.env** 文件的设置将被添加到 $_SERVER$_ENV 中。作为副作用,这意味着如果您的 CodeIgniter 应用程序(例如)正在生成 var_dump($_ENV)phpinfo()(用于调试或其他有效原因),或者在 development 环境中显示详细的错误报告,则 **您的安全凭据将公开暴露**。

嵌套变量

为了节省输入,您可以通过将变量名用 ${...} 包裹来重复使用您已经在文件中指定的变量。

BASE_DIR = "/var/webroot/project-root"
CACHE_DIR = "${BASE_DIR}/cache"
TMP_DIR = "${BASE_DIR}/tmp"

命名空间变量

有时您会遇到多个同名变量。系统需要一种方法来识别正确的设置。这个问题可以通过对变量进行“命名空间”来解决。

命名空间变量使用点符号来限定变量名,以便在合并到环境中时保持唯一性。这可以通过在变量名前添加一个区分前缀,后跟一个点 (.),然后是变量名本身来实现。

// not namespaced variables
name = "George"
db = my_db

// namespaced variables
address.city = "Berlin"
address.country = "Germany"
frontend.db = sales
backend.db = admin
BackEnd.db = admin

命名空间分隔符

某些环境(例如 Docker、CloudFormation)不允许变量名包含点 (.)。在这种情况下,从 v4.1.5 版本开始,您也可以使用下划线 (_) 作为分隔符。

// namespaced variables with underscore
app_forceGlobalSecureRequests = true
app_CSPEnabled = true

配置类和环境变量

当您实例化一个配置类时,任何命名空间的环境变量都会被考虑合并到配置对象的属性中。

重要

您不能通过设置环境变量来添加新的属性,也不能将标量值更改为数组。请参见 环境变量作为数据的替换.

注意

此功能在 CodeIgniter\Config\BaseConfig 类中实现。因此,它不适用于 app/Config 文件夹中不扩展该类的几个文件。

如果命名空间变量的前缀与配置类的命名空间完全匹配,则设置的尾部(点之后)将被视为配置属性。如果它与现有的配置属性匹配,则环境变量的值将替换配置文件中的对应值。如果没有匹配,则配置类的属性将保持不变。在这种用法中,前缀必须是类的完整(区分大小写)命名空间。

Config\App.forceGlobalSecureRequests = true
Config\App.CSPEnabled = true

注意

命名空间前缀和属性名称都区分大小写。它们必须与配置类文件定义的完整命名空间和属性名称完全匹配。

同样适用于短前缀,它是一个仅使用配置类名称的小写版本的命名空间。如果短前缀与类名匹配,则来自 .env 的值将替换配置文件的值。

app.forceGlobalSecureRequests = true
app.CSPEnabled = true

从 v4.1.5 开始,您也可以使用下划线编写

app_forceGlobalSecureRequests = true
app_CSPEnabled = true

注意

使用短前缀时,属性名称必须与类定义的名称完全匹配。

环境变量作为数据的替换

务必始终记住,.env 中包含的环境变量只是现有数据的替换

简而言之,您只能通过在 .env 中设置来更改 Config 类中存在的属性值。

您不能添加 Config 类中未定义的属性,也不能将定义属性的值更改为数组,即使该属性的值是标量。

例如,您不能只是在您的 **.env** 文件中添加 app.myNewConfig = foo,并期望您的 Config\App 在运行时神奇地拥有该属性和值。

当您在 Config\Database 中拥有属性 $default = ['encrypt' => false] 时,即使您在 **.env** 文件中添加 database.default.encrypt.ssl_verify = true,您也不能将 encrypt 值更改为数组。如果您想这样做,请参阅 数据库配置

将环境变量视为数组

命名空间环境变量可以进一步被视为数组。如果前缀与配置类匹配,则如果环境变量名称也包含点,则环境变量名称的其余部分将被视为数组引用。

// regular namespaced variable
Config\SimpleConfig.name = George

// array namespaced variables
Config\SimpleConfig.address.city = "Berlin"
Config\SimpleConfig.address.country = "Germany"

如果这是指 SimpleConfig 配置对象,则上面的示例将被视为

<?php

$address['city']    = 'Berlin';
$address['country'] = 'Germany';

$address 属性的任何其他元素将保持不变。

您也可以使用数组属性名称作为前缀。如果环境文件包含以下内容,则结果将与上面相同。

// array namespaced variables
Config\SimpleConfig.address.city = "Berlin"
address.country = "Germany"

处理不同的环境

通过使用单独的 **.env** 文件,其中包含修改后的值以满足该环境的需求,可以轻松地配置多个环境。

该文件不应包含应用程序使用的每个配置类的所有可能设置。实际上,它应该只包含特定于环境的项目,或者敏感信息,如密码和 API 密钥以及其他不应公开的信息。但是,任何在部署之间发生变化的项目都是可以的。

在每个环境中,将 **.env** 文件放置在项目的根文件夹中。对于大多数设置,这将与 app 目录处于同一级别。

不要使用您的版本控制系统跟踪 **.env** 文件。如果您这样做,并且存储库被公开,您将把敏感信息放在每个人都可以找到的地方。

注册器

“注册器”是任何其他可能提供额外配置属性的类。注册器提供了一种在运行时跨命名空间和文件更改配置的方法。

如果在 模块 中启用了 自动发现,则注册器有效。它在实例化 Config 对象时更改配置属性。

实现注册器有两种方法:**隐式** 和 **显式**。

注意

来自 **.env** 的值始终优先于注册器。

隐式注册器

隐式注册器可以更改任何 Config 类属性。

任何命名空间都可以通过使用 **Config/Registrar.php** 文件来定义隐式注册器。这些文件是类,其方法以您希望扩展的每个配置类的名称命名。

例如,第三方模块或 Composer 包可能希望向 Config\Pager 提供一个额外的模板,而不会覆盖开发人员已经配置的内容。在 **src/Config/Registrar.php** 中,将有一个 Registrar 类,其中包含单个 Pager() 方法(注意大小写敏感性)。

<?php

namespace CodeIgniter\Shield\Config;

class Registrar
{
    public static function Pager(): array
    {
        return [
            'templates' => [
                'module_pager' => 'MyModule\Views\Pager',
            ],
        ];
    }
}

注册器方法必须始终返回一个数组,其键对应于目标配置文件的属性。现有值将被合并,并且注册器属性具有覆盖优先级。

显式注册器

显式注册器只能更改它们注册的 Config 类属性。

配置文件还可以显式指定任意数量的注册器。这是通过在配置文件中添加一个 $registrars 属性来完成的,该属性保存候选注册器名称的数组。

<?php

namespace Config;

// ...

class MyConfig extends BaseConfig
{
    public static $registrars = [
        SupportingPackageRegistrar::class,
    ];

    // ...
}

为了充当“注册器”,如此标识的类必须具有与配置类同名的静态函数,并且它应该返回一个关联数组的属性设置。

当您的配置对象被实例化时,它将循环遍历 $registrars 中指定的类。对于这些类中的每一个,它将调用以配置类命名的函数,并将任何返回的属性合并。

此配置类的示例设置

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class MySalesConfig extends BaseConfig
{
    public int $target        = 100;
    public string $campaign   = 'Winter Wonderland';
    public static $registrars = [
        '\App\Models\RegionalSales',
    ];
}

…以及相关的区域销售模型可能如下所示

<?php

namespace App\Models;

class RegionalSales
{
    public static function MySalesConfig(): array
    {
        return [
            'target' => 45,
        ];
    }
}

在上面的示例中,当 MySalesConfig 被实例化时,它将最终拥有三个声明的属性,但 $target 属性的值将被覆盖,方法是将 RegionalSales 视为“注册器”。最终的配置属性

<?php

$target   = 45;
$campaign = 'Winter Wonderland';