第1章 遇见PhalApi

古云此日足可惜,吾辈更应惜秒阴。——董必武《惜时》

1.1 PhalApi是什么?

PhalApi,简称:π框架,是一个国产开源的PHP轻量级接口开发框架,专注于接口服务开发,支持HTTP/SOAP/RPC协议,可用于快速搭建微服务、RESTful接口或Web Services。

1.2 PhalApi的前世今生

1.2.1 前世:个人框架zenphpWS3

PhalApi最初是始于2012年个人毕业论文的项目开发需要。

由于当时课题是开发一个基于旅游轨迹的图片分享平台,需要开发一套提供给App客户端使用的后台服务接口。 然而,在实际项目开发中,发现身边很多团队在使用PHP进行接口开发时,往往是很简单,或者说是很粗爆的,如直接使用fopen()函数获取远程接口的执行结果再加以处理。尴尬的是,当时在寻找一个可以用于快速后台接口开发的PHP框架时,没找到合适贴切的开源框架。准确来说来,没找到一个专注于接口开发的开源框架。

基于此,萌生了自主研发一个接口框架的想法。经过到图书馆和网上查阅整理多方资料、知识和理论,和一段时间的设计及编码后,便延生了最初的接口框架,并命名为: zenphpWS3。 其中,zen表示开源、php表示用PHP开发、WS表示Web Service、3表示支持SOAP、HTTP或RPC三种协议以及JSON、XML或数组等多种格式的返回。

zenphpWS3很好地支撑毕业论文项目的开发,并初步具备了一个框架的基本特质与思想。但经过一年的全职工作,以及学习、研究众多优秀开源构架后,发现还存在很多有待改善的地方。所以,当再次使用zenphpWS3进行新接口项目开发时,我便在开发具体应用接口服务的同时,也有意识地在对接口框架进行完善和重构,并融入框架所需要的特性、原则和模式。如可重用、IoC、SOILD设计原则、组件和容器等。至此,通过不断演进迭代,一个更好的接口框架便慢慢浮现了出来。

1.2.2 今生:开源框架PhalApi

与此同时,我们迎来了移动互联网的浪潮。很多大的企业都提供了开放平台,如腾讯开放平台、新浪微博开放平台、优酷开放平台等。而对于中型公司或者初创团队,则需要为自主的APP开发提供特定领域业务功能的接口服务。也就是说,越来越多的项目需要像我当初那样开发接口服务,但也可能同样会像我当初那样面临找不到合适贴切开源框架的困境。

秉着希望能帮助更多同学快速开发接口项目的初衷,我便再次对此接口框架进行重构优化,于2015年正式走向开源,并更名为:PhalApi,简称:π框架。

正如PHPUnit的作者Sebastian Bergmann所说的那样:

Driven by his passion to help developers build better software.

同样,我们希望通过PhalApi,可以:

  • 一来,支撑轻量级接口项目的快速开发;
  • 二来,阐明如何更好地进行接口开发、设计和维护;
  • 三来,分享优秀的编程思想、实用的工具和精益求精的技艺。

最初的接口框架就在这样的背景和研究下出来了。

1.3 接口,从简单开始!

1.3.1 一个隐喻

假设我们有一条这样的表达式:

1 + 1 = 2

显然,这是非常简单,且易于理解的。但倘若我们在中间添加一些复杂性后:

1 + (96 - 867 + 700 - 6 + 7 - 30/10 + 100  - 27) +  1 = 2

同样可以获得相同的结果,但表达却羞涩难懂,且容易出错。

你可能会觉得好笑:怎么可能会有人把这么简单的问题复杂化呢?还编写这么累赘的代码?然而,如果你回顾一下以往接触过的项目或留意一下身边正在运行的代码,你会发现,这种情况是真实存在的。

在不同的领域开发不同的项目,各自需求不同,所编写的代码也就不尽相同。纵使这样,即使我们不能把代码简化到最理想的状态,但至少可以通过努力以达到“编写人容易理解的代码”这一最佳状态。一如这样:

1 + (0) +  1 = 2

1.3.2 PhalApi框架所做的

使用PhalApi框架进行接口项目开发,我们不能保证最终编写出来的项目代码一定会“短而美”,因为更多的代码编写来自于你双手的输入、来自你自己切身的思考和设计。但我们希望PhalApi可以在支持接口快速开发的基础上,为你和更多开发团队提供关于接口项目开发的一些技艺、参考和帮助。

所以,与其他很多关注服务器性能的框架不同, PhalApi更加关注的是人的心情、开发效率和团队合作,而这些正是通过约束与规范、测试驱动开发、自动化工具、持续集成和敏捷开发等途径可以达成的 。

这一切一切,都要从代码的编写开始。毕竟我们作为专业软件开发人士,代码是我们连接世界的媒介。而接口代码的编写,又应从简单开始。

泡一杯咖啡,让我们开始吧。

1.4 下载与安装

PhalApi框架的最新版本的代码,可以到Github进行下载。

https://github.com/phalapi/phalapi  

也可以到国内的码云上进行下载。

http://git.oschina.net/dogstar/PhalApi

这两个仓库的代码会同步一致,开发人员可根据自己的喜欢选择使用。

其中,release分支为中文稳定版;release-en分支为英文稳定版。需要使用PHP 5.3.3及以上版本。

安装如同其他的框架一样,将下载的框架压缩包上传到服务器后解压即可。结合自己的喜爱与项目需要,可以采用Apache、XAMPP、Microsoft IIS等。根据使用的服务器不同,配置也不一样。

本书所使用的环境是:

  • PHP 5.3.10
  • Nginx 1.1.19
  • PhalApi 1.4.0
  • Ubuntu 12.04(64位)

所以在这里,本书统一约定使用PhaApi 1.4.0 版本,并且推荐使用Nginx作为服务器。以这里的环境安装为例,假设框架解压的目录为:/path/to/PhalApi/Public,则首先需要添加Nginx配置文件api.phalapi.net,然后重启Nginx,最后添加HOST并访问。

即首先,新建一个配置文件:

# vim /etc/nginx/sites-available/api.phalapi.net

并添加以下参考配置:

server {
    listen 80;
    server_name api.phalapi.net;

    root /path/to/PhalApi/Public;
    charset utf-8;

    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    access_log logs/api.phalapi.net.access.log;
    error_log logs/api.phalapi.net.error.log;
}

接着,创建软链:

# ln -s /etc/nginx/sites-available/api.phalapi.net /etc/nginx/sites-enabled/api.phalapi.net

重启Nginx服务:

$ /etc/init.d/nginx restart

并在服务器的/etc/hosts文件里添加:

127.0.0.1 api.phalapi.net

最后在浏览器访问Demo的默认接口服务,测试接口是否可以正常访问,如请求:

http://api.phalapi.net/demo/

正常情况下,会看到类似以下这样的返回结果。

{
    "ret": 200,
    "data": {
        "title": "Hello World!",
        "content": "PHPer您好,欢迎使用PhalApi!",
        "version": "1.4.0",
        "time": 1492346885
    },
    "msg": ""
}

温馨提示: 为了可视化JSON结果,Chrome浏览器可安装JSONView扩展,Firefox可以安装JSON-handel扩展。

1.5 创建一个新项目

安装好后,可以使用在线可视化安装向导来创建一个新的项目。

安装向导在目录./Public/install/下,在浏览器输入http://api.phalapi.net/install/便可访问此安装向导。安装界面如下:

图1-1 安装向导

图1-1 安装向导

随后按照提示,一步步操作即可。创建新项目过程,会要求输入项目名称。假设我们需要为商城创建一个项目,并命名为:shop,那么安装完成后访问效果如下。

图1-2 新建shop项目的运行效果

图1-2 新建shop项目的运行效果

这时,可以看到新建了以下目录和文件。

$ tree ./Shop/ ./Public/shop/
./Shop/
├── Api
│   └── Default.php
├── Common
├── Domain
├── Model
└── Tests
    ....

./Public/shop/
├── checkApiParams.php
├── index.php
└── listAllApis.php

对于各个目录,简单说明如下:

  • ./Shop:放置项目源代码,每个项目对应一个目录
  • ./Shop/Api:接口服务类目录
  • ./Shop/Domain:领域业务类目录
  • ./Shop/Model:数据模型类目录
  • ./Shop/Common:公共目录
  • ./Shop/Tests:单元测试目录

以上都是外界不可直接访问的目录,下面则是对外可访问的目录和文件。

  • ./Public/shop:外部可访问的目录
  • ./Public/shop/index.php:入口文件
  • ./Public/shop/listAllApis.php:在线接口列表文档
  • ./Public/shop/checkApiParams.php:在线接口详情文档

关于各个目录和各个文件的作用,后续会作进一步说明。

至此,我们已经取到了阶段性的成果。我们完成了框架的安装与部署,还创建了一个新的项目。接下来,让我们继续探索一下,如何在PhalApi下进行具体的接口编码开发。

1.6 Hello World

遵循国际惯例,这里编写的第一个接口也是Hello World。这是一个非常简单的接口,主要功能是返回“Hello World”这串字符。  

继续使用上面已创建的shop项目。首先,创建一个接口类文件./Shop/Api/Welcome.php,并在这里实现主要的功能。

// ./Shop/Api/Welcome.php
<?php
class Api_Welcome extends PhalApi_Api {

    public function say() {
        return 'Hello World';
    }
}

然后,便可以对接口进行访问了。如最简单的方式,还是使用浏览器来访问。接口访问的格式为:接口域名 + 入口路径 + ?service=XXX.XXX,所以此接口服务对应的链接为:

http://api.phalapi.net/shop/?service=Welcome.Say

结果默认以JSON格式返回,即正常情况下会看到:

{"ret":200,"data":"Hello World","msg":""}

以上代码和运行结果截图如下。

图 1-3 Hello World代码与运行结果

图1-3 Hello World代码与运行结果

是不是发现接口开发很简单?

当然,这里只是一个很简单的Hello World示例。实际项目开发中,所遇到的业务场景会更为复杂,所面临的技术挑战也会更为深奥。虽然是一个简单示例,但也很好地帮助了我们对PhalApi的开发和使用有了感性的认识,同时察觉到在进行接口开发时需要时刻保持前瞻性和注重细节。例如细心的读者会发现,这里返回的是一个字符串,若日后需要在这个接口添加其他字段的返回则难以保持向前兼容性。所以,离细致的接口开发,我们还有一段路要走。希望这本书,可以陪你更好、更顺畅、更愉悦地度过这段美妙的旅途!

1.7 对PhalApi框架的抉择

能使用框架来进行项目开发,和知道为何使用此框架进行项目开发明显不同。对框架的选择,名义上是架构师的职责,但对于充满好奇心和有着更强求知欲的开发人员来说,同样应该给予关注。

之所以选择一个框架进行项目开发,表面上是为了减少不必要的重复代码;但更深层次,则是为了减少开发周期、统一开发规范、降低项目风险,最终快速迭代、持续交付,不致于项目失控。

在决定使用PhalApi框架前,对于此框架是否适用于即将启动的项目进行一番思索,是大有裨益的。通过推定框架,有助于避免因采用不当的框架而对项目造成不必要的阻力。

1.7.1 适用的场景和项目

PhalApi框架特别适用于当前为各 移动App 或其他后台系统开发远程接口服务。可用于搭建高访问量、大数据存储的接口项目,可以挂靠多个接口项目,也可以很好地支持多个终端、多个版本、多个访问入口。此外,还提供各种可重用的扩展类库,便于快速开发。

基于此,我们采用了主流设计,即将框架设计成默认使用HTTP协议访问,并以JSON格式返回请求结果。因为HTTP协议和JSON格式,都是当前大众所熟悉的。

1.7.2 敏捷开发和快速交付

虽然框架和工程实践间没有必然的联系,但我想其中应该会有一些微妙的联系。一种代码编写的方式会形成一种开发的风格;一种开发风格会奠定一个团队的合作氛围;一个团队的合作氛围会决定项目交付的质量。 而PhalApi所提倡和希望做到的正是通过让接口开发更简单,让后台开发人员心情更愉悦,从而为客户端提供高质量的接口服务。此外,结合重构、测试驱动开发和持续集成等,可以让你的项目如虎添翼,在快速交付的同时,体验编码开发的乐趣。

1.7.3 约束和关注

架构约束程序。 约束有时会让开发者处处受阻。但好的约束能够统一规范而不致于项目代码凌乱不堪,也不会轻易地允许低级开发新手犯下一些本可避免的BUG。正如,我们都讨厌等待红绿灯,但我们必须肯定它对交通和生命安全保障的作用。

1.7.4 复杂领域业务的应对和解决方案

正如前面说到的,我们关注在海量数据下为移动App提供稳定的接口,我们提倡敏捷开发下的快速交付。所以我们去掉与接口开发无关的功能,没有提供视图渲染和模板解析的操作。

但只是这样而已吗?

不!我们还关注对复杂领域业务的应对和解决方案。

如果我们PhalApi框架所关注的,也是你们项目所关注的,那么我们有理由相信PhalApi能为你的项目带来很多友好的约束和贴心的帮助。

1.7.5 框架的性能

很多框架都要强调其能提供的性能,然后PHP本身就是动态的脚本语言,要想提高项目的运行速度,就是要进行减法,即减少不必要的PHP代码。但是前面强调性能的框架则做了与其承诺矛盾的做法:为框架增添了很多项目可能不需要用到的功能。明显地就是一系列既定的执行流程和侦听事件、回调、调度等等。而这些,势必会对性能有所影响,特别当应用项目不需要这些特性却又不能定制简化时,框架所谓的强悍功能会适得其反。

对于这一块,我们则提供了极大的空间。因为,入口和初始化文件,我们可以自由定制。除了一些必要的加载外,很多都可以支持自定义和定制化。而且我们也使用Autobench进行了压力测试和通过XHprof进行了性能剖析,证明PhalApi框架在性能上确实如我们预料的那样——快!

1.7.6 成熟度与学习成本

不可否认,PhalApi还是太年轻了。PhalApi正式开源于2015年1月,但是我们一直都在努力完善,我们尽量“减少不必要的创新”,我们坚持像恒星一般完美支持框架升级,我们尽量提供优秀的文档、及时的沟通和技术帮助。更为重要的是,这是一个不只为框架而框架的PhalApi框架。

“人法地,地法天,天法道,道法自然”。以前经常听说老子这句话,但对于其中的意思最初是不明白的,甚至误解的。“法”字,在这里是学习、效仿的意思。我则把这句稍微简化了一下,精简成:人法自然。在自然界中,无论是石头缝之间的小草,公园里植物,还是山上的生态环境,不管你来不来,它们都一直欣欣而向荣、充满活力。我们应该学习自然这种品质,忠于自己。PhalApi也一样,一直在努力成长,保持生气,为开源社区负责。不会因为使用的人多了就迷乱,也不会因为使用的人少就停止不前。

在开发过程中,对于PhalApi不能很好解决和支持的问题,你也可以考虑尝试优化框架,将某一目标或属性提升至架构,其他团队成员则可从中获益。相信你会发现,在PhalApi下,你可以轻松做到这一点: 小步快跑下的浮现式设计

本章小结

PhalApi是一个国产开源的PHP轻量级接口开发框架,专注于接口服务开发。对于接口,我们应该从简单开始!但在决定选择PhalApi进行项目开发前,应该先评估一番,看下此框架是否满足待开启的项目的要求。在这一章,我们还学习了PhalApi的下载和安装,以及如何创建一个新项目,也尝试编写了第一个Hello World程序。做好了这些准备后,我们便可以踏上新的征途。但在成为一名娴熟的工匠之前,我们还需要掌握一些基础知识。接下来——

参考资料

《恰如其份的框架》推定框架。
《浮现式设计》

Fork me on GitHub