-
Notifications
You must be signed in to change notification settings - Fork 3
Home
写这个框架的起因,是因为公司项目中用到的 Yaf 框架不能很好的满足需求。
在前不久写单元测试时,发现由于 Yaf 对命名空间支持的不足导致没办法写出期望的单元测试代码,除非大量修改业务代码才能绕过去,得不偿失。
具体可参考我给 Yaf 提的 issue https://github.com/laruence/yaf/issues/417
于是,开始考虑是否替换掉 Yaf 框架。
Yaf 框架我个人很喜欢,简单灵活高效不废话,且作为 PHP 扩展运行能几乎忽略框架本身的开销。 市面上也有其它非常优秀的框架,但各自侧重点不一样,很难选出一个像 Yaf 这样精简高效的框架。
所以便有了 Zim 框架,基于 Zephir 开发编译为 PHP 扩展,尽量避免框架本身开销,性能比 Yaf 要差一点,不过可接受。 同时足够简单,仅提供基础特性:命名空间、路由分发、配置、事件、依赖注入等。
代码大部分来自 Laravel 和 Symfony 组件,然后翻译成 zephir 代码并编译为 PHP 扩展。
于是,同时提供了 zim-php
和 zim-ext
两个项目,功能相同,只是前者为 php 实现,后者为扩展。
完整的命名空间支持,遵循 PSR-4 规范
无需配置路由规则,默认根据 uri 分发到对应的 controller 和 action (类似 Yaf)。
如:
uri | controller | action | 备注 |
---|---|---|---|
/ | IndexController | indexAction | |
/foo | FooController | indexAction | |
/foo/bar | FooController | barAction | |
/xx | IndexController | xxAction | 如果 XxController 不存在 |
另外,controller 文件内可以通过 $actions
来指定 action 文件,类似 Yaf
如下, /page
会分发到 PageAction
的 execute
方法
use App\Action\Index\PageAction;
class IndexController extends Controller
{
protected $actions = [
'page' => PageAction::class,
];
}
基于 Symfony/Routing 组件,去掉了 host, schema 等匹配支持。
配置文件 config/routes.php
,
可以通过 Route::get
Route::post
等快捷方式定义路由,如下:
use \Zim\Routing\Route;
// 分发至 FooController barAction
Route::get('/foo/bar', 'Foo@bar');
// 参数 id 为数字,且默认为 1
Route::get('/user/{id<\d+>?1}', 'User@show');
// page 参数为数字且默认值 123,对应到闭包的第一个参数
Route::post('/page/{page<\d+>?123}', function($page) {
return 'page '.$page;
});
// 同时匹配多个 method
Route::match(['POST', 'PUT', 'GET'], '/put', function() {
return 'test match';
});
// 除通过 Route 快捷方法外,也可直接 return 路由定义规则
return [
'/' => 'Index@index',
'/closure' => function() {
return 'closure ok';
},
'/post/{page<\d+>?1}' => 'Index@post',
'/demo' => 'Demo/Index@test',
'/hello/{world}' => [
'to' => 'Index@hello',
'methods' => ['GET', 'POST'],
'requirements' => [
'world' => '\d+',
],
'defaults' => ['world' => 2]
],
];
注:
默认路由、Route
快捷方法 以及配置的路由规则,三者同时生效。
优先级:快捷方法 > 路由规则 > 默认路由
Action 是处理 Http 请求的单元,有以下几种方式:
- 路由定义的闭包
- controller 文件内的某个 xxAction 方法
- controller actions 配置的某个 Action 文件内的 execute 方法
响应数据,正常应为 Zim\Http\Response
对象,同时,可 return 标量来由框架自行判断:
Route::get('/page', function() {
return 'page test';
});
//数组会自动响应为 json
Route::get('/json', function() {
return ['k' => 'v'];
});
默认配置文件 config/app.php
,获取配置可通过 Zim::config('app.name')
如果新增配置文件 config/xx.php
,可通过 Zim::config('xx.key')
获取
类似 Laravel
Zim
基于 Laravel
的 Container
,精简到仅保留核心注册、绑定、扩展三个功能。
同时,简化了对象初始化自动注入机制,应用于对象管理、路由、事件、Controller Action等各方面。
示例,action 内注入 Config
:
public function pageAction($page = 2, Config $config)
{
return [
'page' => $page,
'config' => $config->all(),
];
}
具体可参考 Zim\Container\MagicInjection
参考 Laravel service provider
自定义 Service 类继承 Zim\Service
,且加入到配置 app.services
内
Service 提供两个方法
register
方法,初始化时调用,仅用于容器注册、绑定等,不建议用于业务处理(因为业务用到的容器对象可能还未初始化)
boot
方法,用于业务逻辑,在路由分发前调用。
事件系统同时参考了 Laravel 和 Symfony 的处理方式。
发出事件
Event::fire(new MyEvent());
监听事件
Event::listen($events, function($event, $payload) {});
Http 完整生命周期内均提供了系统事件可订阅或修改 Request
Response
等数据
系统事件如下:
Zim\Event\RequestEvent
Zim\Event\DispatchEvent
Zim\Event\ResponseEvent
Zim\Event\ExceptionEvent
示例,监听系统响应事件并修改响应数据:
class AppService extends Service
{
public function boot()
{
Event::listen(ResponseEvent::class, function($event, $resp) {
$resp->setResponse(new Response('test response event'));
});
}
TODO