终于受不了 Yaf,写了个精简框架 Zim,可作为 PHP 扩展运行

SurreyAurora 发布于1年前
0 条问题

关于

写这个框架的起因,是因为公司项目中用到的 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

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

Service

参考 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

查看原文: 终于受不了 Yaf,写了个精简框架 Zim,可作为 PHP 扩展运行

  • smallgoose
  • smallmeercat
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。