最近闲着没事,自己撸了个轻量级的API框架。不是什么大项目,就是想把自己这些年用的一些东西整理一下,顺便分享一下设计思路,给大家参考参考。
一、为什么要自己造轮子?
可能有人会问,现在那么多成熟的框架,Laravel、ThinkPHP、Slim什么的,为什么还要自己写?
说实话,这些框架都很好,但有时候就是太\"重\"了。我就想写个简单的API,返回几条数据,结果要加载一堆文件,引入一堆依赖。虽然现在服务器配置都不差,但这种浪费总让我觉得不舒服。
另外,自己写框架也是一种学习。很多东西用别人的时候觉得理所当然,自己动手才发现里面有很多门道。
二、整体架构
我的设计原则是:够用就好,不过度设计。
整个框架就几个核心模块:
1. 路由模块:解析URL,匹配到对应的控制器方法
2. 控制器:处理业务逻辑
3. 模型:数据库操作,封装了一些常用的CRUD
4. 中间件:请求前后的处理,比如鉴权、日志等
5. 响应格式化:统一返回JSON格式
没有视图层,因为这本来就是API框架,不需要渲染页面。
三、路由设计
路由我做得比较简单,采用配置文件的方式:
return [
\'GET /user/:id\' => \'UserController@get\',
\'POST /user\' => \'UserController@create\',
\'PUT /user/:id\' => \'UserController@update\',
\'DELETE /user/:id\' => \'UserController@delete\',
];
这种写法我觉得比较直观,一眼就能看明白。:id这种占位符会自动提取出来放到参数里。
四、数据库操作
这块我偷了个懒,直接用了PDO,然后在上面封了一层简单的ORM。支持链式调用,但不支持复杂的关联查询,因为我觉得那种东西很容易把代码搞乱。
基本用法:
// 查询
$users = DB::table(\'users\')->where(\'status\', 1)->get();
// 插入
DB::table(\'users\')->insert([\'name\' => \'test\', \'email\' => \'test@example.com\']);
// 更新
DB::table(\'users\')->where(\'id\', 1)->update([\'status\' => 0]);
够用就行,太复杂的查询直接写SQL好了。
五、中间件机制
中间件是个好东西,可以把一些通用的处理逻辑抽离出来。比如:
- 认证中间件:验证token,获取用户信息
- 日志中间件:记录请求日志
- 限流中间件:防止接口被刷
我的实现方式是责任链模式,请求依次经过各个中间件,最后到达控制器。
六、错误处理
API接口最怕的就是报错,一报错用户就看到一堆HTML代码,很不专业。
我做了一个统一的错误处理器,所有异常都会被捕获,然后返回标准的JSON格式:
{
\"code\": 500,
\"message\": \"服务器内部错误\",
\"data\": null
}
开发环境下会把具体的错误信息也返回出来,方便调试。
七、性能方面
简单测试了一下,一个简单的查询接口,QPS能到5000+,比Laravel快了大概3倍。当然这种测试意义不大,只能说明框架本身的开销确实很小。
八、后续计划
目前这个框架只是自己用,还不太完善。后面打算:
1. 加上缓存支持(Redis)
2. 完善文档
3. 写几个示例项目
4. 如果时机成熟,可能会开源
九、总结
自己造轮子不一定是为了取代谁,更多是一种学习过程。通过这个项目,我对PHP的理解又深了一层。
框架的代码量也就2000多行,感兴趣的朋友可以自己试试,真的不难。有问题欢迎留言讨论。
