在 Swoole 上运行 Symfony

Swoole 的官方网站定义其为『PHP的异步、并行、高性能网络通信引擎』,而对于类似 Symfony 以及 laravel 等每次请求都需要初始化大量代码的巨型框架来说,swoole 可以让初始化框架代码的过程限定在启动服务器时,而非每次请求都初始化,从而极大提升框架的运行效能。关于 swoole 以及类似的 ReactPHP 库让框架运行效率提升多少倍的话题,网上已经有太多,这里不多说。本篇只说目前网上讨论还比较少的话题:如何将 Symfony 跑在 Swoole 上。

前段时间创建了基于 Symfony Flex 的示例项目,这次就基于此项目,让其跑在 swoole 上。

Swoole 官网上提供的代码,已经可以看出 swoole http server 的基本用法:

通过对 swoole http server 的事件监听器中的 $request$response 变量,我们可以获取各种请求信息和发出各种响应信息。

对比 Symfony 的前端控制器代码 web/index.php

其实也是将 $request 通过框架内核的 $kernel->handle 方法,转变成 $response 对象并发送给客户端。

但因 swoole 提供的 $request 对象接口跟 Symfony 的 $request 并不一致,Symfony 的框架内核与 swoole 的 $request 接口无法兼容,此时只能考虑将 swoole 的 $request 对象转换成 Symfony 的请求对象。

不过还好,转换工作不是那么的复杂,我们通过定义转化方法就能解决这个问题:

为了写起来方便,这里使用了 PHP7 新的『语法糖』 $foo ?? $bar,等价于 isset($foo) ? $foo : $bar,关于更多 PHP7 新语法,可见我之前关于 PHP 7.0PHP 7.1 的博客。

与请求对象的情况类似,响应的用法也并不一样。我们也需要通过稍稍修改,让 Symfony 的响应对象,为 swoole 的响应对象提供响应数据:

当然,因为 swoole 完全成了一个 http server,有一些静态文件还是需要处理,原理跟 nginx 类似,如果按照请求的路径能找到本地文件,那么就把本地文件内容原封不动发出去,当然,还要给头信息里配上合适的 mime_type:

当然,此代码略显简陋,判断 mime_type 最好是使用 mime_content_type 方法,但因为此方法需要对 PHP 进行一些配置,也懒得说了。除此之外还有一些第三方库也是可以专门用来判断 mime_type 的,但跟这次主题不符就不多说了。

简单修改后的完整代码如下,注意初始化 Symfony 内核的那段代码一定要放在 swoole 事件处理代码的上面,否则使用 swoole 就没多大意义了

将此代码保存为 web/server.php,然后运行

然后打开浏览器访问 http://localhost:8000/admin,可以发现 Symfony Flex 的演示项目在 swoole 上也能跑了。

为什么说次修改只是『简单的修改』,是因为类似对 session 的处理,还没有涉及到。swoole 是一个看上去挺有前途的项目,但目前是否可以上生产使用还是一个问题,因为它跟传统的 PHP 网站开发的方式还有很多不同,还不知道到底有多少坑。

另外我特别想吐槽一点,swoole 的作者似乎对标准化并没有放在心上,导致 swoole http server 要用在别的框架上还比较困难。其实 PSR7 标准已经出来很久了,Symfony 也发布了 Symfony Request/Response 和 PSR7 标准之间相互转化的 bridge,swoole 上也提了相关的 issue 但也是很长时间并没有得到推进。如果 swoole http server 能拥抱 PSR7 标准,我想它将在 PHP 世界更有市场。

wx pay

CC BY-NC-ND 4.0 在 Swoole 上运行 Symfony by Chrisyue's Blog is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

发表评论

电子邮件地址不会被公开。