Config 组件¶
概览¶
几乎所有应用程序都需要配置数据以保证正常运行。这些配置包括日志文件位置、数据库连接值、注册的服务等参数和初始设置。Phalcon\Config\Config的设计目的是以一种简单、面向对象的方式来存储这些配置数据。
它表示一棵树,其叶节点是配置值。每个Phalcon\Config\Config的子节点都有一个名称,它要么是一个包含配置值的叶子节点,要么是自身为Phalcon\Config\Config实例的子集合,用于保存嵌套值。它提供了访问此类配置集合的方法。每个Phalcon\Config\Config实例代表一个虚拟对象,可以像真实对象属性一样进行遍历。
该类可以直接使用PHP数组实例化,也可以通过读取各种格式的配置文件来实例化,具体方式将在适配器章节中进一步介绍。Phalcon\Config\Config扩展了Phalcon\Support\Collection对象,并继承了它的功能。
<?php
use Phalcon\Config\Config;
$config = new Config(
    [
        'app' => [
            'baseUri'  => getenv('APP_BASE_URI'),
            'env'      => getenv('APP_ENV'),
            'name'     => getenv('APP_NAME'),
            'timezone' => getenv('APP_TIMEZONE'),
            'url'      => getenv('APP_URL'),
            'version'  => getenv('VERSION'),
            'time'     => microtime(true),
        ],
    ]
);
echo $config->get('app')->get('name');  // PHALCON
echo $config->app->name;                // PHALCON
echo $config->path('app.name');         // PHALCON
工厂¶
newInstance¶
 允许的name值,对应不同的适配器类有:创建Phalcon\Config\Config或任何支持的适配器类(Phalcon\Config\Adapter\*),使用new类。然而,Phalcon 提供了Phalcon\Config\ConfigFactory类可以轻松地实例化 config 对象非常简便。调用newInstance方法时传入name, fileName和parameters数组将返回新的配置对象。
允许的name值,对应不同的适配器类,如下所示:
| 名称 | 适配器 | 
|---|---|
grouped |  Phalcon\Config\Adapter\Grouped | 
ini |  Phalcon\Config\Adapter\Ini | 
json |  Phalcon\Config\Adapter\Json | 
php |  Phalcon\Config\Adapter\Php | 
yaml |  Phalcon\Config\Adapter\Yaml | 
例如,创建一个新的PHP 数组作为基础的适配器:
给定一个 PHP 配置文件/app/storage/config.php
<?php
return [
    'app' => [
        'baseUri'  => getenv('APP_BASE_URI'),
        'env'      => getenv('APP_ENV'),
        'name'     => getenv('APP_NAME'),
        'timezone' => getenv('APP_TIMEZONE'),
        'url'      => getenv('APP_URL'),
        'version'  => getenv('VERSION'),
        'time'     => microtime(true),
    ],
];
,你可以按如下方式加载:
<?php
use Phalcon\Config\ConfigFactory;
$fileName = '/app/storage/config.php';
$factory  = new ConfigFactory();
$config = $factory->newInstance('php', $fileName);
第三个参数newInstance是一个数组,在这种情况下不是必须的。但是,其他类型的适配器可能会使用它,因此可以根据适配器类型提供相应的参数。关于parameters数组中可能包含的内容的更多信息,请参阅适配器部分。
load¶
 The Phalcon\Config\ConfigFactory还提供了load方法,接受字符串或数组作为参数。如果传递的是字符串,则将其视为要加载的文件的fileName,并且文件扩展名决定使用的适配器。
<?php
use Phalcon\Config\ConfigFactory;
$fileName = '/app/storage/config.php';
$factory  = new ConfigFactory();
$config = $factory->load($fileName);
如果传递的是数组,则必须包含adapter元素以指定要创建的适配器。此外,filePath是必需的,用于指定要加载的文件所在的位置。关于数组中可能包含内容的更多信息,请参见适配器部分。
给定一个 INI 配置文件/app/storage/config.ini
超全局变量。如果cookie存在于任一集合中,则返回load函数将创建一个Ini配置对象:
<?php
use Phalcon\Config\ConfigFactory;
$fileName = '/app/storage/config.ini';
$factory  = new ConfigFactory();
$config = $factory->load($fileName);
异常¶
在Phalcon\Config\Config组件中抛出的任何异常类型为Phalcon\Config\Exception。你可以使用此异常选择性地捕获仅从此组件抛出的异常。
php
<?php
use Phalcon\Config\Exception;
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
    public function index()
    {
        try {
            // Get some configuration values
            $this->config->database->dbname;
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }
}
原生数组¶
The Phalcon\Config\Config组件接受构造函数中的PHP数组并加载它。
<?php
use Phalcon\Config\Config;
$config = new Config(
    [
        'app' => [
            'baseUri'  => getenv('APP_BASE_URI'),  // '/'
            'env'      => getenv('APP_ENV'),       // 3
            'name'     => getenv('APP_NAME'),      // 'PHALCON'
            'timezone' => getenv('APP_TIMEZONE'),  // 'UTC'
            'url'      => getenv('APP_URL'),       // 'http://127.0.0.1',
            'version'  => getenv('VERSION'),       // '0.1'
            'time'     => microtime(true),         // 
        ],
    ]
);
获取¶
魔术方法¶
使用键作为属性(魔术方法)检索数据:
get()¶
 使用get()方法并链式调用来遍历嵌套对象:
由于Phalcon\Config\Config扩展了Phalcon\Support\Collection,你还可以在get()中传入第二个参数,当配置项未定义时,将返回该默认值。
路径¶
使用path()允许方便地获取任意深度的子项。必填参数是一个字符串,表示所请求节点的路径。这个字符串是一个路径名,包含了从第一层开始的每个祖先节点及自身的名称。根节点的路径名为一个空字符串,第一层节点的路径名就是它自己的名称。第二层及以上节点的路径名由其父节点路径名加上分隔符(默认为.)再加自身的名称组成。
path()也接受一个defaultValue参数,若设置了此参数,当配置对象中找不到或未设置该元素时,将返回此值。最后一个参数path()接受的是路径名中各名称之间的分隔符(必填参数)。
<?php
echo $config->path('app-name', 'default', '-');     // PHALCON
echo $config->path('app-unknown', 'default', '-');  // default
使用getPathDelimiter()和setPathDelimiter()方法获取和设置Config 默认使用的分隔符。
函数式编程与path()结合使用,可用于获取配置数据:
<?php
use Phalcon\Di\Di;
use Phalcon\Config\Config;
/**
 * @return mixed|Config
 */
function config() {
    $args = func_get_args();
    $config = Di::getDefault()->getShared('config');
    if (empty($args)) {
       return $config;
    }
    return call_user_func_array(
        [$config, 'path'],
        $args
    );
}
然后你可以这样使用它:
<?php
echo config('app-name', 'default', '-');     // PHALCON
echo config('app-unknown', 'default', '-');  // default
注意
如果你的数据中的键包含特殊字符,比如.或-,而你又选择在使用path()方法时使用相同的字符作为分隔符,那么你将无法得到预期的结果,因为path()会将分隔符解释为一个新的嵌套层级。
合并¶
有时候我们可能需要合并来自两个不同配置对象的配置数据。例如,我们可能有一个配置对象包含基本/默认设置,而另一个配置对象则加载特定于应用程序运行环境的选项(如测试、开发、生产等)。系统特定的数据可以从.env文件加载,并通过DotEnv库进行处理。
在上面的场景中,我们需要将第二个配置对象与第一个合并。merge()允许我们这样做,递归地合并这两个配置对象。
<?php
use Phalcon\Config\Config;
use josegonzalez\Dotenv\Loader;
$baseConfig = new Config(
    [
        'app' => [
            'baseUri'  => '/',
            'env'      => 3,
            'name'     => 'PHALCON',
            'timezone' => 'UTC',
            'url'      => 'http://127.0.0.1',
            'version'  => '0.1',
        ],
    ]
);
// .env
// APP_NAME='MYAPP'
// APP_TIMEZONE='America/New_York'
$loader = (new josegonzalez\Dotenv\Loader('/app/.env'))
    ->parse()
    ->toEnv()
;
$envConfig= new Config(
    [
        'app'     => [
            'baseUri'  => getenv('APP_BASE_URI'),  // '/'
            'env'      => getenv('APP_ENV'),       // 3
            'name'     => getenv('APP_NAME'),      // 'MYAPP'
            'timezone' => getenv('APP_TIMEZONE'),  // 'America/New_York'
            'url'      => getenv('APP_URL'),       // 'http://127.0.0.1',
            'version'  => getenv('VERSION'),       // '0.1'
            'time'     => microtime(true),         //
        ],
        'logging' => true,
    ]
);
$baseConfig->merge($envConfig);
echo $baseConfig
        ->get('app')
        ->get('name');  // MYAPP
echo $baseConfig
        ->get('app')
        ->get('timezone');  // America/New_York
echo $baseConfig
        ->get('app')
        ->get('time');  // 1562909409.6162
合并后的对象将是:
Phalcon\Config Object
(
    [app] => Phalcon\Config Object
        (
            [baseUri]  => '/',
            [env]      => 3,
            [name]     => 'MYAPP',
            [timezone] => 'America/New_York',
            [url]      => 'http://127.0.0.1',
            [version]  => '0.1',
            [time]     => microtime(true),
        )
    [logging] => true
)
是否存在¶
使用has()你可以判断集合中是否存在某个特定键。
设置¶
该组件还支持set()这个方法允许你以编程方式添加或修改已加载的数据。
序列化¶
该对象可以通过serialize()方法序列化并保存到文件或缓存服务中。使用unserialize方法可以实现反向操作。
toArray / toJson¶
 如果你需要将对象转换回数组形式,toArray()和toJson()提供了相关方法。
更多信息,请查看 [Phalcon\Support\Collection][support-collection] 文档。
适配器¶
除了核心组件Phalcon\Config\Config设计上可接受字符串(文件名和路径)或原生PHP数组外,还有多个适配器可用。这些适配器有助于读取各种类型的文件以加载配置数据。
可用的适配器¶
| 类 | 描述 | 
|---|---|
| Phalcon\Config\Adapter\Grouped | 根据相同或不同的适配器加载不同的配置文件。 | 
| Phalcon\Config\Adapter\Ini | 从 INI 文件中加载配置。内部此适配器使用 PHP 函数parse_ini_file. |  
| Phalcon\Config\Adapter\Json | 从 JSON 文件中加载配置。需要系统中包含 PHPjson扩展。 |  
| Phalcon\Config\Adapter\Php | 从 PHP 多维数组中加载配置。这个适配器提供了最佳性能。 | 
| Phalcon\Config\Adapter\Yaml | 从 YAML 文件中加载配置。需要系统中包含 PHPyaml扩展。 |  
组合式(Grouped)¶
The Phalcon\Config\Adapter\Grouped适配器允许从多个来源创建一个Phalcon\Config\Config对象,而无需单独创建每个对象。它接受一个带有必要数据的数组配置,默认使用 php 作为默认适配器。
多维数组的构造函数参数包括:
adapter- 要使用的适配器filePath- 配置文件的路径
<?php
use Phalcon\Config\Adapter\Grouped;
$options = [
    [
        'adapter'  => 'php',
        'filePath' => '/apps/storage/config.php',
    ],
    [
        'adapter'  => 'ini',
        'filePath' => '/apps/storage/database.ini',
        'mode'     => INI_SCANNER_NORMAL,
    ],
    [
        'adapter'  => 'json',
        'filePath' => '/apps/storage/override.json',
    ],
];
$config = new Grouped($options);
每个数组元素(表示一个配置文件)设置的键名与各个适配器的构造函数参数相对应。关于所需或可选参数的更多信息,请参阅描述各适配器的相关部分。
你还可以使用array作为适配器值。如果你选择这样做,则需要使用config作为第二个键,其值代表你想要加载的配置的实际值。
<?php
use Phalcon\Config\Adapter\Grouped;
$options = [
    [
        'adapter'  => 'php',
        'filePath' => '/apps/storage/config.php',
    ],
    [
        'adapter'  => 'array',
        'config'   => [
            'app' => [
                'baseUri'  => '/',
                'env'      => 3,
                'name'     => 'PHALCON',
                'timezone' => 'UTC',
                'url'      => 'http://127.0.0.1',
                'version'  => '0.1',
            ],
        ],
    ],
];
$config = new Grouped($options);
最后,一个Phalcon\Config\Config对象也可以作为组合对象的一个选项。
<?php
use Phalcon\Config\Config;
use Phalcon\Config\Adapter\Grouped;
$baseConfig = new Config(
    [
        'app' => [
            'baseUri'  => '/',
            'env'      => 3,
            'name'     => 'PHALCON',
        ],
    ]
);
$options = [
    $baseConfig,
    [
        'adapter'  => 'array',
        'config'   => [
            'app' => [
                'timezone' => 'UTC',
                'url'      => 'http://127.0.0.1',
                'version'  => '0.1',
            ],
        ],
    ],
];
$config = new Grouped($options);
Ini¶
The Phalcon\Config\Adapter\Ini适配器使用优化后的 PHP 函数parse_ini_file来从 INI 文件中读取配置。每个小节代表一个顶层元素,如果键中包含.分隔符,则子元素会嵌套。默认的扫描方式是INI_SCANNER_RAW,但可以通过在构造函数中传入不同的模式来覆盖该设置。
示例 INI 文件:
[database]
adapter  = Mysql
host     = localhost
username = scott
password = cheetah
dbname   = test_db
[config]
adapter  = ini
filePath = PATH_DATA"storage/config"
mode = 1
[models]
metadata.adapter  = 'Memory'
使用方式:
<?php
use Phalcon\Config\Adapter\Ini;
$fileName = '/apps/storage/config.ini';
$mode     =  INI_SCANNER_NORMAL;
$config   = new Ini($fileName, $mode);
echo $config
        ->get('database')
        ->get('host');       // localhost
echo $config
        ->get('models')
        ->get('metadata')
        ->get('adapter');    // Memory
当使用Phalcon\Config\ConfigFactory,将模式作为参数设置:
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.ini';
$factory  = new ConfigFactory();
$options = [
    'adapter'  => 'ini',
    'filePath' => $fileName,
    'mode'     => INI_SCANNER_NORMAL, 
];
$config = $factory->load($options);
或者在使用newInstance():
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.ini';
$factory  = new ConfigFactory();
$params = [
    'mode' => INI_SCANNER_NORMAL, 
];
$config = $factory->newinstance('ini', $fileName, $params);
Json¶
注意
需要 PHP 的json扩展存在于系统中
JSON 是一种广泛使用的格式,适用于应用程序之间传输数据以及存储配置数据。Phalcon\Config\Adapter\Json内部使用json_decode()将 JSON 文件转换为原生 PHP 数组并进行解析。
示例 JSON 文件:
{
  "database": {
    "adapter": "Mysql",
    "host": "localhost",
    "username": "scott",
    "password": "cheetah",
    "dbname": "test_db"
  },
  "models": {
    "metadata": {
      "adapter": "Memory"
    }
  }
}
使用方式:
<?php
use Phalcon\Config\Adapter\Json;
$fileName = '/apps/storage/config.json';
$config   = new Json($fileName);
echo $config
        ->get('database')
        ->get('host');       // localhost
echo $config
        ->get('models')
        ->get('metadata')
        ->get('adapter');    // Memory
对于Phalcon\Config\ConfigFactory,传入文件名:
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.json';
$factory  = new ConfigFactory();
$options = [
    'adapter'  => 'json',
    'filePath' => $fileName,
];
$config = $factory->load($options);
或者在使用newInstance():
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.json';
$factory  = new ConfigFactory();
$config = $factory->newinstance('json', $fileName);
Php¶
The Phalcon\Config\Adapter\Php适配器读取一个返回数组的 PHP 文件,并将其加载到Phalcon\Config\Config对象中。配置可以以 PHP 数组的形式存储在一个文件中,适配器将读取并解析它。
示例 PHP 文件:
<?php
return [ 
    'database' => [
        'adapter'  => 'Mysql',
        'host'     => 'localhost',
        'username' => 'scott',
        'password' => 'cheetah',
        'dbname'   => 'test_db',  
    ],
    'models'   => [
        'metadata' => [
            'adapter' => 'Memory',
        ],
    ],
];
使用方式:
<?php
use Phalcon\Config\Adapter\Php;
$fileName = '/apps/storage/config.php';
$config   = new Php($fileName);
echo $config
        ->get('database')
        ->get('host');       // localhost
echo $config
        ->get('models')
        ->get('metadata')
        ->get('adapter');    // Memory
对于Phalcon\Config\ConfigFactory,传入文件名:
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.php';
$factory  = new ConfigFactory();
$options = [
    'adapter'  => 'php',
    'filePath' => $fileName,
];
$config = $factory->load($options);
或者在使用newInstance():
<?php
use Phalcon\Cache\CacheFactory;
$fileName = '/app/storage/config.php';
$factory  = new ConfigFactory();
$config = $factory->newinstance('php', $fileName);
Yaml¶
注意
需要系统中存在 PHP 的 yaml 扩展
YAML 是另一种常见的文件格式,Phalcon\Config\Adapter\Yaml需要yamlPHP 扩展。它使用 PHP 函数yaml_parse_file来读取 YAML 文件。该适配器接受第二个参数 callbacks,作为一个提供 YAML 节点内容处理程序的数组。
示例 YAML 文件:
app:
  baseUri: /
  env: 3
  name: PHALCON
  timezone: UTC
  url: http://127.0.0.1
  version: 0.1
  time: 1562960897.712697
models:
  metadata:
    adapter: Memory
loggers:
  handlers:
    0:
      name: stream
    1:
      name: redis
使用方式:
<?php
use Phalcon\Config\Adapter\Yaml;
define("APPROOT", dirname(__DIR__));
$fileName  = '/apps/storage/config.yml';
$callbacks = [
    "!approot" => function($value) {
        return APPROOT . $value;
    },
];
$config    = new Yaml($fileName, $callbacks);
echo $config
        ->get('database')
        ->get('host');       // localhost
echo $config
        ->get('models')
        ->get('metadata')
        ->get('adapter');    // Memory
对于Phalcon\Config\ConfigFactory,将模式作为参数设置:
<?php
use Phalcon\Cache\CacheFactory;
define("APPROOT", dirname(__DIR__));
$fileName = '/apps/storage/config.yml';
$factory  = new ConfigFactory();
$options  = [
    'adapter'  => 'yaml',
    'filePath'  => $fileName,
    'callbacks' => [
        "!approot" => function($value) {
            return APPROOT . $value;
        },
    ],
];
$config = $factory->load($options);
或者在使用newInstance():
<?php
use Phalcon\Cache\CacheFactory;
define("APPROOT", dirname(__DIR__));
$fileName  = '/app/storage/config.yaml';
$factory   = new ConfigFactory();
$callbacks = [
    "!approot" => function($value) {
        return APPROOT . $value;
    },
];
$config = $factory->newinstance('yaml', $fileName, $callbacks);
自定义¶
如需更多适配器,请探索Phalcon孵化器.
依赖注入¶
与大多数 Phalcon 组件一样,您可以将Phalcon\Config\Config对象存储在您的Phalcon\Di\Di容器。通过这样做,你可以从控制器、模型、视图以及任何实现Injectable.
的组件中访问你的配置对象。服务注册和容器访问示例:
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Config\Config;
// Create a container
$container = new FactoryDefault();
$container->set(
    'config',
    function () {
        $configData = require 'config/config.php';
        return new Config($configData);
    }
);
现在可以在控制器中通过config键访问该组件:
<?php
use Phalcon\Mvc\Controller;
use Phalcon\Config\Config;
/**
 * @property Config $config
 */
class MyController extends Controller
{
    private function getDatabaseName()
    {
        return $this->config->database->dbname;
    }
}
在视图中也同样适用(Volt 语法)