博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Just for fun——Slim借力Swoole
阅读量:6800 次
发布时间:2019-06-26

本文共 6271 字,大约阅读时间需要 20 分钟。

Slim

的话,是一个遵循 (PSR-7)规范微型的框架,作者这样说:

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs. At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.

大致意思:slim的核心工作:分发了Http请求,然后调用回调函数,返回一个Http response对象。

Slim其实就帮我们做了两件事

  1. 路由的分发
  2. 依赖的注入

框架很小,所以别的部分(如db操作、模板引擎)可能需要自己实现,但slim通过,让你可以很轻松的组装其他功能到slim中。

快速入门:

[ 'addContentLengthHeader' => false,]];$app = new \Slim\App($config);// Define app routes$app->get('/hello/{name}', function ($request, $response, $args) { return $response->write("Hello " . $args['name']);});// Run app$app->run();

request代表了当前请求对象,response代表了当前响应对象,$args是占位符的键值对数组。

访问/hello/salamander就会输出Hello salamander

添加依赖

是我自己封装的一个PDO的操作类。

$config = ['settings' => [    'addContentLengthHeader' => false,]];$app = new \Slim\App($config);$container = $app->getContainer();$container['db'] = function($c) {    $dbHost = 'localhost';    $dbName = 'test';    $dbConf = [        'dsn' => "mysql:dbname={$dbName};host={$dbHost}",        'username' => "root",        'password' => "******",        'charset' => 'utf8'    ];    $db = new \App\Library\DB();    $db->__setup($dbConf);    return $db;};// Define app routes$app->get('/user/{uid}', 'App\Controller\IndexController:index');

IndexController类

namespace App\Controller;class IndexController {    protected $container;        public function __construct(ContainerInterface $container) {        $this->container = $container;    }        public function index($request, $response, $args) {        $info = $this->container['db']->fetch('SELECT name FROM user WHERE uid = :uid', [            'uid' => $args['uid']        ]);        echo "user name is " . $info['name'];    }}

IndexController类的是通过composer自动载入的(代码中没写):

"autoload": {    "psr-4": {        "App\\": "app/"    }},

代码中可以发现,依赖容器的注入是在类实例化的时候发生的。执行IndexController的index方法时,我们从$container中取出的db依赖,这时候,注册的回调函数被调用,返回实例。因为是用到时才实例化,这个叫做延迟实例化

结合Swoole

让PHP可以常驻内存,而且它提供了Http Server的功能,所以Slim和Swoole没什么冲突。

思考

Slim是通过当前路由(譬如/user/2,不带查询字符串)和http方法来找到正确的回调函数的。这些量Slim是从哪里取的呢?肯定是$_SERVER。查看slim源码:

run()方法:

public function run($silent = false){    $response = $this->container->get('response');    try {        ob_start();        $response = $this->process($this->container->get('request'), $response);    } catch (InvalidMethodException $e) {        $response = $this->processInvalidMethod($e->getRequest(), $response);    } finally {        $output = ob_get_clean();    }    if (!empty($output) && $response->getBody()->isWritable()) {        $outputBuffering = $this->container->get('settings')['outputBuffering'];        if ($outputBuffering === 'prepend') {            // prepend output buffer content            $body = new Http\Body(fopen('php://temp', 'r+'));            $body->write($output . $response->getBody());            $response = $response->withBody($body);        } elseif ($outputBuffering === 'append') {            // append output buffer content            $response->getBody()->write($output);        }    }    $response = $this->finalize($response);    if (!$silent) {        $this->respond($response);    }    return $response;}

发现$request对象是从容器取出来的,那$request是怎么注册的呢??,那就看App类的构造函数了,最后发现Container类的构造函数中有registerDefaultServices()方法:

private function registerDefaultServices($userSettings){    $defaultSettings = $this->defaultSettings;    /**     * This service MUST return an array or an     * instance of \ArrayAccess.     *     * @return array|\ArrayAccess     */    $this['settings'] = function () use ($userSettings, $defaultSettings) {        return new Collection(array_merge($defaultSettings, $userSettings));    };    $defaultProvider = new DefaultServicesProvider();    $defaultProvider->register($this);}

查看$defaultProvider->register()方法:

public function register($container){    if (!isset($container['environment'])) {        /**         * This service MUST return a shared instance         * of \Slim\Interfaces\Http\EnvironmentInterface.         *         * @return EnvironmentInterface         */        $container['environment'] = function () {            return new Environment($_SERVER);        };    }    if (!isset($container['request'])) {        /**         * PSR-7 Request object         *         * @param Container $container         *         * @return ServerRequestInterface         */        $container['request'] = function ($container) {            return Request::createFromEnvironment($container->get('environment'));        };    }        //...

可以看到$request对象是通过Request::createFromEnvironment方法构造的,它需要从容器中取出environment依赖,而environment依赖是通过构造一个Environment对象得来的,它正好放入了$_SERVER

查看Environment类源码,可以发现它继承了Collection类,Collection的构造函数如下:

public function __construct(array $items = []){    $this->replace($items);}

从上面我们可以得出,我们主要注册一个自定义的environment依赖就行,原来$_SERVER的信息可以从swoole的$request->server中取。

简单实现

server.php

on("start", function ($server) { echo "Swoole http server is started at http://0.0.0.0:8888\n";});$http->on("request", function ($request, $response) { // Instantiate the app $config = [ 'settings' => [ 'addContentLengthHeader' => false, ] ]; $config['environment'] = function () use($request) { $server = []; foreach ($request->server as $key => $value) { $server[strtoupper($key)] = $value; } return new Environment($server); }; $app = new \Slim\App($config); // Register routes require APP . '/routes.php'; // Run app $slimResponse = $app->run(true); $headers = $slimResponse->getHeaders(); foreach ($headers as $name => $values) { $response->header($name, implode(", ", $values)); } $response->header("X-Powered-By", "Salamander"); $response->end($slimResponse->getBody());});$http->start();

注意$request->server中key都是小写的,所以这里转化了一下。

routes.php(在App目录中)

get('/', function (Request $request, Response $response) { $response->getBody()->write('Hello Salamander'); return $response;});$app->get('/user/{uid}', function (Request $request, Response $response, $args) { $response->getBody()->write('Hello User:' . $args['uid']); return $response;});

测试

访问/

clipboard.png

访问/user/45

clipboard.png

打包下载测试

tip:环境基于docker的,运行docker-compose up即可

Github上的讨论

转载地址:http://tiywl.baihongyu.com/

你可能感兴趣的文章
用RMAN 备份异机恢复 迁移数据(一)dave
查看>>
Redis参数一览
查看>>
数据库日常运维中的几个操作建议
查看>>
Java基础-String类常用方法
查看>>
轻量级移动设备即时通讯技术MobileIMSDK的常见问题解答
查看>>
管理H3C交换机
查看>>
Java_Index
查看>>
thymeleaf th:href 多个参数传递格式
查看>>
2008R2 组策略的应用
查看>>
enum
查看>>
java自增的陷井
查看>>
Apache2.4版本环境下基于虚拟主机、ssl、用户控制
查看>>
要卖的四本书的封面
查看>>
Linux下puppet安装
查看>>
python笔记--集合
查看>>
系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式
查看>>
区别Ruby的require,load,和include
查看>>
VMware view连接vCenter提示证书错误,无法连接vCenter服务器
查看>>
http协议
查看>>
cobbler快速部署
查看>>