TP5学习-配置文件

在ThinkPHP中[1],一般来说应用的配置文件是自动加载的, 加载的顺序是:

惯例配置->应用配置->扩展配置->场景配置->模块配置->动态配置

0x01 配置介绍

  • 惯例配置

位于thinkphp/convention.php, 相当于系统的默认配置

  • 应用配置

默认位于application/config.php,应用初始化时首先加载的公共配置文件,每个应用初始化的配置,这个是个文件夹,文件可对应convention中的一部分

  • 模块配置

对应每个模块的配置文件

  • 动态配置

RT

0x02 ArrayAccess

ArrayAccess提供像访问数组一样的方式访问对象的接口

接口

1
2
3
4
5
ArrayAccess {
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public boolean offsetExists ( mixed $offset )
abstract public void offsetUnset ( mixed $offset )

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php

class ObjAray implements \ArrayAccess{

private $testdata = [
"title" => "heheda",
];

# 判断存在
public function offsetExists($offset)
{
// TODO: Implement offsetExists() method.
echo 'offsetExists'. $offset;
return isset($offset);
}

# 获取
public function offsetGet($offset)
{
// TODO: Implement offsetGet() method.
echo 'offsetGet'. $offset;
return $this->testdata[$offset];
}

# 设置
public function offsetSet($offset, $value)
{
// TODO: Implement offsetSet() method.
echo 'offsetSet'. $offset;
$offset = $value;
}

# 删除
public function offsetUnset($offset)
{
// TODO: Implement offsetUnset() method.
unset($offset);
}

调用

1
2
3
4
5
public function obj() {
$obj = new \ObjAray();
# 像 数组一样使用
var_dump($obj['title']);
}

0x3 流程分析

  1. 配置文件

通常是php,yaml格式需要安装扩展,tp还提供了一些其他格式(ini,json,xml)以驱动的方式通过工厂模式parse

  1. 方法
  • set: 设置配置
  • get: 获得配置

加载

系统从应用程序入口run()方法来到框架中的initialize()(.php -> .php),这里会调用初始化方法init()init()中有自动读取配置文件模块。

自动读取配置文件代码段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
     // 自动读取配置文件
# 找config目录位置
if (is_dir($path . 'config'))
{
$dir = $path . 'config' . DIRECTORY_SEPARATOR;
}
elseif (is_dir($this->configPath . $module))
{
$dir = $this->configPath . $module;
}

# 获得文件列表并加载
$files = isset($dir) ? scandir($dir) : [];

foreach ($files as $file) {
#.php
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
$this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));
}

这里加载配置文件会使用load()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 拿到文件路径和文件前缀(ex. ../cache.php, cache)
public function load($file, $name = '')
{
if (is_file($file))
{
$filename = $file;
}
elseif (is_file($this->path . $file . $this->ext))
{
$filename = $this->path . $file . $this->ext;
}

if (isset($filename))
{
# 拿到php配置文件内容
return $this->loadFile($filename, $name);
}
// Yaconf设置
elseif ($this->yaconf && Yaconf::has($file))
{
return $this->set(Yaconf::get($file), $name);
}
return $this->config;
}

这里会判断是否使用了Yaconf扩展[2],如果使用了有一个标量可以判断然后进入这个块。然鹅我并没有用过这个。

看加载文件的loadFile()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected function loadFile($file, $name)
{
$name = strtolower($name);
$type = pathinfo($file, PATHINFO_EXTENSION);

if ('php' == $type)
{
# php配置文件->load->loadFile->set
return $this->set(include $file, $name);
}
# 通过function_exists判断是否安装该模块
elseif ('yaml' == $type && function_exists('yaml_parse_file'))
{
return $this->set(yaml_parse_file($file), $name);
}
# 非php和yaml走到这
return $this->parse($file, $type, $name);
}

这里区分加载了上边说的三类配置文件类型,直接加载的.php文件,需要扩展的.yaml文件以及用工厂模式加载的那三类(ini,json,xml)。这个parse感兴趣的可以走走,跑路了:>。

set

加载了文件,还需要set方法来设置配置

如在加载loadFile()中加载应用配置的时候, 调用是 return $this->set(include $file, $name);set方法接收是public function set($name, $value = null)就感觉很怪,可能我还没能理解意图。如传入app.php这个应用配置,$name是配置数组,而$value是文件名前缀。接下来如果是数组就进入批量设置,然后如果有$this->configarray_merge没有就创建一个。然后赋上$name,对$name是内容,$value应该是做key来用,代码我就不贴了哈。

参考

[1] ThinkPHP5.0完全开发手册

[2] Yaconf – 一个高性能的配置管理扩展