Slim的話,是一個遵循PSR (PSR-7)規範微型的框架,做者這樣說:php
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對象。mysql
Slim其實就幫咱們作了兩件事git
框架很小,因此別的部分(如db操做、模板引擎)可能須要本身實現,但slim經過依賴注入,讓你能夠很輕鬆的組裝其餘功能到slim中。github
<?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
web
DB是我本身封裝的一個PDO的操做類。sql
$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');
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自動載入的(代碼中沒寫):docker
"autoload": { "psr-4": { "App\\": "app/" } },
代碼中能夠發現,依賴容器的注入是在類實例化的時候發生的。執行IndexController的index方法時,咱們從$container中取出的db依賴,這時候,註冊的回調函數被調用,返回實例。由於是用到時才實例化,這個叫作延遲實例化。segmentfault
Swoole讓PHP能夠常駐內存,並且它提供了Http Server的功能,因此Slim和Swoole沒什麼衝突。數組
Slim是經過當前路由(譬如/user/2,不帶查詢字符串)和http方法來找到正確的回調函數的。這些量Slim是從哪裏取的呢?確定是$_SERVER
。查看slim源碼:
run()方法:swoole
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; });
訪問/
訪問/user/45
百度雲盤
tip:環境基於docker的,運行docker-compose up
便可