配置
每个框架都使用配置文件来定义各项参数和初始设置。CodeIgniter 的配置文件定义了简单的类,所需设置均作为公共属性。
与许多其他框架不同,CodeIgniter 的配置项并不集中在单个文件中。相反,每个需要配置项的类都有一个同名的配置文件。应用程序配置文件位于 app/Config 目录下。
什么是配置类?
配置类用于定义系统默认配置值。系统配置值通常是 静态 的。配置类旨在保存配置应用运行方式的设置,而不是响应每个用户的个性化设置。
不建议在执行期间修改配置类实例化时设置的值。换言之,建议将配置类视为不可变类或只读类。如果使用了 配置缓存,这一点尤为重要。
配置值可以硬编码在类文件中,也可以在实例化时从环境变量中获取。
使用配置文件
获取 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(\Acme\Blog\Config\Blog::class)),只要存在同名的短类名,config() 也会优先在 app/Config/ 中查找文件。该行为已在 v4.4.0 中修复,现在会返回指定的实例。
获取 Config 属性
所有配置对象的属性都是公共的,因此可以像访问其他属性一样访问设置:
<?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 = 'webmaster@example.com';
// ...
}
环境变量
使用环境变量是目前应用程序设置的最佳实践之一。原因之一是环境变量易于在部署之间更改而无需改动任何代码。配置在部署过程中可能会频繁变动,但代码不会。例如,开发者的本地机器和生产服务器等多个环境,通常需要针对每个特定的设置采用不同的配置值。
环境变量还应用于处理私密信息,如密码、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"
带命名空间的变量
有时会出现多个同名变量的情况。系统需要一种方式来识别正确的设置。这个问题可以通过为变量设置 “命名空间” 来解决。
带命名空间的变量使用点号表示法来限定变量名,确保并入环境时是唯一的。具体做法是包含一个区分前缀,后跟一个点号(.),然后是变量名本身。
// 不带命名空间的变量
name = "George"
db = my_db
// 带命名空间的变量
address.city = "Berlin"
address.country = "Germany"
frontend.db = sales
backend.db = admin
BackEnd.db = admin
命名空间分隔符
某些环境(如 Docker、CloudFormation)不允许变量名包含点号(.)。在这种情况下,自 v4.1.5 起,也可以使用下划线(_)作为分隔符。
// 使用下划线的带命名空间的变量
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 的值更改为数组。如需此类操作,请参阅 数据库配置。
将环境变量视为数组
带命名空间的环境变量可以进一步被视为数组。如果前缀与配置类匹配,且环境变量名的其余部分也包含点号,则该部分将被视为数组引用。
// 普通带命名空间的变量
Config\SimpleConfig.name = George
// 数组带命名空间的变量
Config\SimpleConfig.address.city = "Berlin"
Config\SimpleConfig.address.country = "Germany"
如果上述变量引用的是 SimpleConfig 配置对象,则会按如下方式处理:
<?php
$address['city'] = 'Berlin';
$address['country'] = 'Germany';
$address 属性的其他任何元素都将保持不变。
也可以使用数组属性名作为前缀。如果环境文件中包含以下内容,结果将与上述相同。
// 数组带命名空间的变量
Config\SimpleConfig.address.city = "Berlin"
address.country = "Germany"
处理不同环境
通过使用单独的 .env 文件并根据环境需求修改其中的值,可以轻松配置多个环境。
该文件不应包含应用程序所使用的每个配置类的所有可能设置。实际上,它应仅包含特定于环境的项目,或者诸如密码、API 密钥等不应公开的敏感细节。不过,任何在部署之间发生变化的内容都可以包含在内。
在每个环境中,将 .env 文件放置在项目的根目录下。对于大多数设置,这与 app 目录同级。
不要使用版本控制系统跟踪 .env 文件。如果这样做且存储库被公开,敏感信息将会暴露给所有人。
注册器
“注册器”是指任何可能提供额外配置属性的其他类。注册器提供了一种在运行时跨命名空间和文件更改配置的方法。
如果在 模块 中启用了 自动发现,注册器即可工作。它会在实例化 Config 对象时修改配置属性。
备注
此功能在 CodeIgniter\Config\BaseConfig 类中实现。因此,对于 app/Config 目录下少数未扩展该类的文件,此功能将不起作用。
实现注册器有两种方式:隐式 和 显式。
备注
.env 中的值始终优先于注册器。
隐式注册器
隐式注册器可以更改任何配置类的属性。
任何命名空间都可以通过使用 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',
],
];
}
}
注册器方法必须始终返回一个数组,其键与目标配置文件的属性相对应。现有值会被合并,且注册器属性具有覆盖优先级。
显式注册器
显式注册器只能更改其注册所在的配置类的属性。
配置文件也可以显式指定任意数量的注册器。通过在配置文件中添加一个 $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';
确认配置值
实际的 Config 对象属性值在运行时由 注册器、环境变量 以及 配置缓存 进行更改。
CodeIgniter 提供了以下 命令 来检查实际的配置值。
config:check
Added in version 4.5.0.
例如,如果要检查 Config\App 实例:
php spark config:check App
输出如下所示:
Config\App#6 (12) (
public 'baseURL' -> string (22) "http://localhost:8080/"
public 'allowedHostnames' -> array (0) []
public 'indexPage' -> string (9) "index.php"
public 'uriProtocol' -> string (11) "REQUEST_URI"
public 'defaultLocale' -> string (2) "en"
public 'negotiateLocale' -> boolean false
public 'supportedLocales' -> array (1) [
0 => string (2) "en"
]
public 'appTimezone' -> string (3) "UTC"
public 'charset' -> string (5) "UTF-8"
public 'forceGlobalSecureRequests' -> boolean false
public 'proxyIPs' -> array (0) []
public 'CSPEnabled' -> boolean false
)
Config Caching: Disabled
可以查看配置缓存是否已启用。
备注
如果启用了配置缓存,将永久使用缓存值。有关详情,请参阅 配置缓存。