swoole已是php高性能服务器事实标准,能够参考这个博客使用swoole开发业务框架php
项目地址:github.com/neatlife/pf…html
欢迎star,欢迎prgit
框架执行的核心流程图以下(右键可查看大图): github
swoole是从命令行启动,常驻进程运行,web请求处理依赖的全局变量好比 _GET,
_FILES等不会随着每次请求的改变填上对应的值,swoole把这个每次请求的变量放在了Swoole\Http\Request对象中web
好比把swoole的_SERVER中json
$server = array_change_key_case($request->server, CASE_UPPER);
foreach ($request->header as $key => $val) {
$server['HTTP_' . str_replace('-', '_', strtoupper($key))] = $val;
}
$_SERVER = $server;
复制代码
其它环境变量的对应以下服务器
$_GET = $request->get;
$_POST = $request->post;
$_COOKIE = $request->cookie;
$_FILES = $request->files;
复制代码
swoole的服务器从命令行启动,使用这个Symfony Console组件包装一下能够方便的启动swooleswoole
<?php
class SwooleServerCommand extends Command {
// ...
protected function execute(InputInterface $input, OutputInterface $output) {
$options = $this->parseOption($input);
$http = new HttpServer($options['host'], $options['port']);
$swooleEventHandler = new SwooleEventHandler($this->container);
foreach (self::$swooleEventList as $eventName) {
$http->on($eventName, [$swooleEventHandler, 'on' . ucfirst($eventName)]);
}
echo "server started at {$options['host']}:{$options['port']}..." . PHP_EOL;
$http->start();
}
// ...
}
复制代码
swoole的http事件经过swoole的回调函数触发,这里使用事件分发器,将这个框架的代码尽量和swoole分离,实现松耦合目标cookie
这里使用这个事件分发器处理了swoole的start和request事件composer
建立事件分发器对象
$this->eventDispatcher = new EventDispatcher();
复制代码
分发start和request事件
class SwooleEventHandler {
public function onStart() {
Application::getInstance()->getEventDispatcher()->dispatch(Event::START, new GenericEvent());
}
public function onRequest(Request $request, Response $response) {
$server = array_change_key_case($request->server, CASE_UPPER);
foreach ($request->header as $key => $val) {
$server['HTTP_' . str_replace('-', '_', strtoupper($key))] = $val;
}
$_SERVER = $server;
Application::getInstance()->getEventDispatcher()->dispatch(Event::REQUEST, new GenericEvent($response));
}
}
复制代码
swoole完整的事件列表参考:wiki.swoole.com/wiki/page/4…
使用Symfony的容器来共享应用全部的对象,避免对象重复的建立,而且能够在应用任何位置方便的获取容器中的对象
new ContainerBuilder();
复制代码
$this->container->set(Application::class, $this);
复制代码
$this->container->get(Application::class);
复制代码
中间件通常设计成嵌套调用,这种状况下须要用递归来实现,核心代码以下
protected function callMiddleware($request, $response, $index = 0) {
if (!isset($this->middleware[$index])) {
return $response;
}
$middleware = new $this->middleware[$index];
return $middleware($request, $response, function ($request, $response) use ($index) {
$this->callMiddleware($request, $response, $index + 1);
});
}
复制代码
完整的composer.json依赖以下
"require": {
"symfony/console": "^3.4",
"symfony/event-dispatcher": "^3.4",
"symfony/dependency-injection": "^3.4",
"symfony/http-foundation": "^3.4"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
复制代码
symfony的Request对象没有实现psr的ServerRequestInterface,若是要遵照psr的request,能够考虑其它request组件,好比zend framework带的request
持续更新中...