PHP DIY系列–一起手写一个api框架
那么就利用composer来开始我们的项目吧。
新建目录并进入目录,输入命令:
composer init
命令行会跟你确认以下信息(以下信息可以自行DIY)
# 1. 输入项目命名空间 |
我们的目录下会生成composer.json。
然后我们来思考一个问题:
你觉得一个基础的API框架需要什么模块呢?
下面是我的思考结果:
- 路由
- 请求
- 数据响应
- 异常处理
- 日志系统…
当然,你可能觉得还应该有:
- 配置
- session
- 缓存
- 验证
- 模型
- 服务层
- 文件上传…
也许你想到更多:
- 任务调度
- 队列
- 用户验证
- 锁
- …
那么这么些我们如何取舍呢?手心手背都是肉啊。
这里需要做一下说明,我们所做的框架无需考虑太多的功能,是做一个简单可用的API接口框架,我们接受get/post请求,返回json数据,并且路由好用,这是我们的初衷,其他的暂且就“断舍离”吧。
我们先画一个极简的流程图。

我们一切从简,所以我们定义以下几个模块:
- 路由
- 控制器
- 请求
- 数据响应
- 配置
- 异常处理
- …
基于这些,我们新建目录,app和library,public
- app web应用
- library 核心代码
- public 入口目录
出于简单安全考虑,我们的入口单独放在public目录,并在目录下新建index.php作为我们的入口文件。
library下面新建几个目录和文件
- Components 常用组件
- Exceptions 异常模块
- Https http应用模块
- Sessions session模块
- Application.php 应用文件
- Config.php 配置文件
- Functions.php 常用函数
- System.php 框架自定义常量

对应的我们在composer.json中加入一些autoload配置,用以自动加载,省去我们实现自动加载。
"autoload": { |
执行一下,composer install或者composer dump-autoload即可。
这里简单说明一下autoload的四种方式:
autoload的四种方式
- PSR-4
在psr-4键下,定义了相对于包根目录从名称空间到路径的映射。当自动加载一个类(如foo\bar\baz)时,指向src/目录的名称空间前缀foo\,意味着自动加载程序将查找一个名为src/bar/baz.php的文件,并包括它(如果存在)。注意,与旧的psr-0样式相反,前缀(foo\)不在文件路径中。
命名空间前缀必须以“\”结尾,以避免类似前缀之间的冲突。例如,foo将匹配foobar名称空间中的类,因此后面的反斜杠可以解决问题:foo\,foobar\。
该数组可以在生成的文件vendor/composer/autoload_psr4.php中找到。
- PSR-0
在 psr-0 key 下你定义了一个命名空间到实际路径的映射(相对于包的根目录)。注意,这里同样支持 PEAR-style 方式的约定(与命名空间不同,PEAR 类库在类名上采用了下划线分隔)。
请注意,命名空间的申明应该以 \ 结束,以确保 autoloader 能够准确响应。例: Foo 将会与 FooBar 匹配,然而以反斜杠结束就可以解决这样的问题, Foo\ 和 FooBar\ 将会被区分开来。
PSR-0 引用都将被结合为一个单一的键值对数组,存储至 vendor/composer/autoload_namespaces.php 文件中。

- classmap
你可以用 classmap 生成支持支持自定义加载的不遵循 PSR-0/4 规范的类库。要配置它指向需要的目录,以便能够准确搜索到类文件。
classmap 引用的所有组合会存储到 vendor/composer/autoload_classmap.php 文件中。这个 map 是经过扫描指定目录(同样支持直接精确到文件)中所有的 .php 和 .inc 文件里内置的类而得到的。
- files
如果你想要明确的指定,在每次请求时都要载入某些文件,那么你可以使用 ‘files’ autoloading。通常作为函数库的载入方式(而非类库)。files 引用的文件会存储到 vendor/composer/autoload_files.php 文件中
我们先不着急进行核心代码编写,不妨先做一下辅助工作,常用方法,异常处理等。
常用函数Functions
编写常用函数
<?php |
异常处理
在Exceptions目录下,定义一个最基础的异常SaiException:
<?php |
几乎后面所有Exception的类都会继承这个异常类。
在Components目录下新建基础的类Base:
<?php |
这里有两个知识点:
- ArrayAccess数组式访问接口(提供像访问数组一样访问对象的能力的接口。)
- 魔术方法__set和__get(在给不可访问属性赋值时__set() 会被调用;读取不可访问属性的值时__get() 会被调用。)
如果想了解更多,可看官方文档: