codecamp

定制化:资源服务的再实现

美到极致不是无可增加,而是无可减少。 -- Antonie de Saint-Exupery

2.18.1 资源服务

资源可以理解成接口开发过程中所使用到的第三方系统、功能,如数据库,COOKIE、缓存;而服务则是指领域驱动设计中无状态的服务操作,如加密、过滤器、加载器等。
而在PhalApi中,资源和服务更多是通过DI来统一进行管理。并且我们使用资源服务来统称这两者。

在使用PhalApi进行开发时,应该分别从以下三个层面来使用资源服务。

  • 1、基本使用
  • 2、高级应用
  • 3、定制扩展

其中,基本使用是指使用框架默认提供的特性、功能,只需要稍微修改调整一下配置(甚至连配置都不需要修改)即可使用; 高级应用是指切换使用具有同类特性、功能的资源服务,对客户端而言,其实现的功能是等价的,只在于内部实现不同,通常此层面适用于有不同需求的应用场景; 最后是,定制扩展则是充满活力、生气的做法,对于项目需要用到而框架未提供的,都可以通过此方式进行定制、扩展。

2.18.2 仍然以缓存为例

下面以大家熟悉的缓存为例,分别说明这三个层面的演进使用。

(1)基本使用

在./Public/init.php初始化文件中,我们可以去掉对Memcache的注释,从而在项目启用cache这一资源服务。

//缓存 - Memcache/Memcached
DI()->cache = function () {
    return new PhalApi_Cache_Memcache(DI()->config->get('sys.mc'));
};

或者,我们还需要根据配置的MC不同,稍微更改一下./Config/sys.php中对应的配置:

    /**
     * MC缓存服务器参考配置
     */
     'mc' => array(
           'host' => '127.0.0.1',
           'port' => 11211,
     ),

然后,就可以在项目中如前面说的那样使用cache进行对缓存进行操作。

//设置缓存
DI()->cache->set($key, $value, $expireTime);

//读取缓存
$rs = DI()->cache->get($key);

(2)高级应用

但是我们都知道,缓存的实现方案以及存储的方式多种多样,包括但不限于:数据库缓存、文件缓存、COOKIE/session缓存、Redis缓存、APC缓存。

假设我们需要切换到Redis缓存,则可以在init.php初始化中,把DI()->cache注册成Redis缓存即可。

DI()->cache = function () {
    return new PhalApi_Cache_Redis(DI()->config->get('sys.redis'));
};

同时,在./Config/sys.php中添加对应的配置:

     'redis' => array(
           'host' => '127.0.0.1',
           'port' => 9527,
     ),

(3)定制扩展

毫无疑义,实际项目需要面对的开发场景更为复杂,可能需要使用到加密、压缩、分片或者其他处理手段,又可能使用其他存储媒介。

当框架基本的特性无法满足时,这时就需要考虑进行定制扩展了。值得庆幸的是,实现这一点并不难。一如往常那样,我们需要 先实现、再注册 。

实现资源服务接口

很多通常的资源服务,我们都统一了接口规约。在[1.19]-DI服务速查:各资源服务一览表 中可以查到每个资源服务所需要实现的接口。

如这次的缓存接口类是:

<?php

interface PhalApi_Cache {

    /**
     * 设置缓存
     * 
     * @param string $key 缓存key
     * @param mixed $value 缓存的内容
     * @param int $expire 缓存有效时间,单位秒,非时间戳
     */
    public function set($key, $value, $expire = 600);

    /**
     * 读取缓存
     * 
     * @param string $key 缓存key
     * @return mixed 失败情况下返回NULL
     */
    public function get($key);

    /**
     * 删除缓存
     * 
     * @param string $key
     */
    public function delete($key);
}

我们可以先在项目中,实现此接口,如:

class Common_MyCache implements PhalApi_Cache {
     // ... ...
}

具体的实现,这里不再举例。

再注册

当实现好子类后,我们便可以在init.php初始化文件中,切换到我们自己的定制类。

DI()->cache = 'Common_MyCache';

2.18.3 实现、定制化你的资源服务

正如《项目百态》书中隐藏的美模式一节中写道的“恰恰相反,只有减少特性才能提升设计的美感。最好的设计都是功能明确又留有答题,也是易于测试的,即使要作修改,也不会带来新的麻烦。”

是以,作为一个框架,我们应当以发散的方式去设计;但为了能为应用提供可用的功能,我们又应当以收敛的方式去实现。如果我们提供的功能不足以满足大部分主流的业务场景,那么我们至少需要提供可扩展的空间。

类似的场景,还包括有接口签名、对接口参数的获取与接口结果的返回。当大家在进行项目开发过程中,有不同的场景需求时,可以按上面介绍的三个层面分别进行。

先尝试使用简单、默认的方式进行配置解决,再切换到框架或已有的解决方案,最后再尝试扩展自己的定制类。


微服务:Api接口服务层
扩展库:可重用的扩展类库
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

八、视频教程

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }