配置模块

从零开始编写一个PHP框架 系列的《配置模块》

项目地址:terse

前言

一个扩展性、兼容性强的项目,其可配性肯定很强。

需求分析

  • 可以单个配置
  • 可以批量配置
  • 可以转换成数组

配置

先看一下配置后,类的输出。

object(Terse\Config)#17 (1) {
  ["memcached"]=>
  object(Terse\Config)#18 (2) {
    ["lifetime"]=>
    int(2592000)
    ["server"]=>
    object(Terse\Config)#19 (2) {
      ["host"]=>
      string(9) "memcached"
      ["port"]=>
      int(11211)
    }
  }
}

需要继承的类

这里为了方便使用数组的方式操作配置,所以需要继承 ArrayAccess 接口。

同时,数组一般少不了 count,于是又继承了 Countable 接口。

这里根据具体情况可以进行取舍。

初始化类

通过官方文档可以看出,在继承接口 ArrayAccessCountable 之后,这里需要实现几个方法:

public function count();

public function offsetExists($key);

public function offsetGet($key);

public function offsetSet($key, $value);

public function offsetUnset($key);

设置

这里准备将数组的每个键作为类的属性,比如:

/**
 * 添加配置
 * 
 * @param  string $key
 * @param  mixed  $value
 */
public function set($key, $value)
{
    $this->{$key} = $value;
}

不过,为了统一,在设置时,直接调用 offsetSet 方法,这样在用数组方式赋值时,也会成功。

/**
 * 添加配置
 * 
 * @param  string $key
 * @param  mixed  $value
 */
public function set($key, $value)
{
    $this->offsetSet($key, $value);
}

同样的,如果时批量设置,我们只需要给个循环就OK:

/**
 * 批量添加配置
 * 
 * @param  array  $params
 */
public function batchSet(array $params)
{
    foreach ($params as $key => $value) {
        $this->offsetSet($key, $value);
    }
}

获取

类似设置,在获取时,需要用到 offsetExistsoffsetGet 两个方法,主要是做一个是否存在的检测。

当然,为了使获取功能更加人性化,我们设置了默认值的选项。

/**
 * 获取某个配置
 * 
 * @param  string $key
 * @param  mixed  $default
 * @return mixed
 */
public function get($key, $default = null)
{
    if (!$this->offsetExists($key)) {
        return $default;
    }
    return $this->offsetGet($key);
}

统计

有了设置和获取,那么就可以计算出当前配置类里又多少个键值了。

/**
 * 总计
 * 
 * @return int
 */
public function count()
{
    return count(get_object_vars($this));
}

完善接口方法

是否存在:

/**
 * ArrayAccess offsetExists
 * 
 * @param  string $key
 * @return bool
 */
public function offsetExists($key)
{
    $key = (string)$key;
    return isset($this->{$key});
}

获取:

/**
 * ArrayAccess offsetGet
 * 
 * @param  string $key
 * @return mixed
 */
public function offsetGet($key)
{
    $key = (string)$key;
    if (!$this->offsetExists($key)) {
        return null;
    }
    return $this->{$key};
}

销毁:

/**
 * ArrayAccess offsetUnset
 * 
 * @param  string $key
 */
public function offsetUnset($key)
{
    if ($this->offsetExists($key)) {
        unset($this->{$key});
    }
}

上述的几个方法都很简单,一下子就能看懂,而唯独少了设置的实现。

之所以要把设置单独拿出来,不是因为设置有多麻烦,而是在做的时候,思考过一个问题:先实例化再设置,还是在实例化的时候就设置的问题。

最终,我选择了后者,在实例化的时候就设置。

所以,在构造函数里,我们就需要进行一个批量设置:

/**
 * 配置初始化
 * 
 * @param array $configArr
 */
public function __construct(array $configArr)
{
    if (!$configArr) {
        return true;
    }
    foreach ($configArr as $key => $value) {
        $this->offsetSet($key, $value);
    }
}

那么,在 offsetSet 方法里,也需要对 $value 进行判断,毕竟我们不确定用户配置的是一维数组还是多维数组。

/**
 * ArrayAccess offsetSet
 * 
 * @param  string $key
 * @param  mixed $value
 */
public function offsetSet($key, $value)
{
    $key = (string)$key;
    if (is_array($value)) {
        $this->{$key} = new self($value);
        return true;
    }
    $this->{$key} = $value;
}

转数组

说实话,这个功能有点冗余,毕竟正常情况下用不到,而且,我们基本实现了数组的一些常用功能。

这里用了一个循环,其实主要也是看 $value 是类还是字符串之类的,然后看看是否调用 toArray() 方法。

/**
 * 转换成数组
 * 
 * @return array
 */
public function toArray()
{
    $params = get_object_vars($this);
    $configArr = [];
    foreach ($params as $key => $param) {
        if ($param instanceof self && method_exists($param, 'toArray')) {
            $configArr[$key] = $param->toArray();
            continue;
        }
        $configArr[$key] = $param;
    }
    return $configArr;
}

到此为止,配置类编写结束。

完整代码

<?php
namespace Terse;
/**
* Terse\Config
*
* @link https://gitee.com/imjcw/terse
* @author imjcw <imjcw@imjcw.com>
*/
class Config implements \ArrayAccess, \Countable
{
    /**
     * 配置初始化
     * 
     * @param array $configArr
     */
    public function __construct(array $configArr)
    {
        if (!$configArr) {
            return true;
        }
        foreach ($configArr as $key => $value) {
            $this->offsetSet($key, $value);
        }
    }

    /**
     * 检查某个配置是否存在
     * 
     * @param  string $key
     * @return boolean
     */
    public function has($key)
    {
        return $this->offsetExists($key);
    }

    /**
     * 获取某个配置
     * 
     * @param  string $key
     * @param  mixed  $default
     * @return mixed
     */
    public function get($key, $default = null)
    {
        if (!$this->offsetExists($key)) {
            return $default;
        }
        return $this->offsetGet($key);
    }

    /**
     * 添加配置
     * 
     * @param  string $key
     * @param  mixed  $value
     */
    public function set($key, $value)
    {
        $this->offsetSet($key, $value);
    }

    /**
     * 批量添加配置
     * 
     * @param  array  $params
     */
    public function batchSet(array $params)
    {
        foreach ($params as $key => $value) {
            $this->offsetSet($key, $value);
        }
    }

    /**
     * 转换成数组
     * 
     * @return array
     */
    public function toArray()
    {
        $params = get_object_vars($this);
        $configArr = [];
        foreach ($params as $key => $param) {
            if ($param instanceof self && method_exists($param, 'toArray')) {
                $configArr[$key] = $param->toArray();
                continue;
            }
            $configArr[$key] = $param;
        }
        return $configArr;
    }

    /**
     * 总计
     * 
     * @return int
     */
    public function count()
    {
        return count(get_object_vars($this));
    }

    /**
     * ArrayAccess offsetExists
     * 
     * @param  string $key
     * @return bool
     */
    public function offsetExists($key)
    {
        $key = (string)$key;
        return isset($this->{$key});
    }

    /**
     * ArrayAccess offsetGet
     * 
     * @param  string $key
     * @return mixed
     */
    public function offsetGet($key)
    {
        $key = (string)$key;
        if (!$this->offsetExists($key)) {
            return null;
        }
        return $this->{$key};
    }

    /**
     * ArrayAccess offsetSet
     * 
     * @param  string $key
     * @param  mixed $value
     */
    public function offsetSet($key, $value)
    {
        $key = (string)$key;
        if (is_array($value)) {
            $this->{$key} = new self($value);
            return true;
        }
        $this->{$key} = $value;
    }

    /**
     * ArrayAccess offsetUnset
     * 
     * @param  string $key
     */
    public function offsetUnset($key)
    {
        if ($this->offsetExists($key)) {
            unset($this->{$key});
        }
    }
}

结语

配置模块是一系列模块中比较简单的模块,但也是比较重要的模块,毕竟项目的配置还是需要它来提供的。

下一篇:《日志模块》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容