Just for fun——Slim接力Swoole

栏目: PHP · 发布时间: 8年前

内容简介:Just for fun——Slim接力Swoole

Slim

Slim 的话,是一个遵循 PSR (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中。

快速入门:

<?php
// Create and configure Slim app
$config = ['settings' => [
    '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

添加依赖

DB 是我自己封装的一个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

SwoolePHP 可以常驻内存,而且它提供了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

<?php
use Slim\Http\Environment;

// 定义常量
define("ROOT", getcwd() . '/..');
define('APP', ROOT . '/app');

require ROOT . '/vendor/autoload.php';
// load functions
require APP . '/functions.php';


$http = new swoole_http_server("0.0.0.0", 8888);

$http->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目录中)

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;


$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;
});

测试

访问/

Just for fun——Slim接力Swoole

访问/user/45

Just for fun——Slim接力Swoole

打包下载测试

百度云盘

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


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to Probability Theory and Its Applications

An Introduction to Probability Theory and Its Applications

William Feller / Wiley / 1991-1-1 / USD 120.00

Major changes in this edition include the substitution of probabilistic arguments for combinatorial artifices, and the addition of new sections on branching processes, Markov chains, and the De Moivre......一起来看看 《An Introduction to Probability Theory and Its Applications》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具