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

2.18.1 资源服务

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

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

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

2.18.2 仍然以缓存为例

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

(1)基本使用

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

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

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

  1. /**
  2. * MC缓存服务器参考配置
  3. */
  4. 'mc' => array(
  5. 'host' => '127.0.0.1',
  6. 'port' => 11211,
  7. ),

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

  1. //设置缓存
  2. DI()->cache->set($key, $value, $expireTime);
  3. //读取缓存
  4. $rs = DI()->cache->get($key);

(2)高级应用

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

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

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

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

  1. 'redis' => array(
  2. 'host' => '127.0.0.1',
  3. 'port' => 9527,
  4. ),

(3)定制扩展

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

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

实现资源服务接口

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

如这次的缓存接口类是:

  1. <?php
  2. interface PhalApi_Cache {
  3. /**
  4. * 设置缓存
  5. *
  6. * @param string $key 缓存key
  7. * @param mixed $value 缓存的内容
  8. * @param int $expire 缓存有效时间,单位秒,非时间戳
  9. */
  10. public function set($key, $value, $expire = 600);
  11. /**
  12. * 读取缓存
  13. *
  14. * @param string $key 缓存key
  15. * @return mixed 失败情况下返回NULL
  16. */
  17. public function get($key);
  18. /**
  19. * 删除缓存
  20. *
  21. * @param string $key
  22. */
  23. public function delete($key);
  24. }

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

  1. class Common_MyCache implements PhalApi_Cache {
  2. // ... ...
  3. }

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

再注册

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

  1. DI()->cache = 'Common_MyCache';

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

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

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

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

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

原文: https://www.phalapi.net/wikis/2-18.html