/** * Run application * * This method traverses the application middleware stack and then sends the * resultant Response object to the HTTP client. * * @param bool|false $silent * @return ResponseInterface * * @throws Exception * @throws MethodNotAllowedException * @throws NotFoundException */ public function run($silent = false) { $request = $this->container->get('request'); $response = $this->container->get('response'); $response = $this->process($request, $response); if (!$silent) { $this->respond($response); } return $response; }
$request = $this->container->get('request');php
if (!isset($this['request'])) { /** * PSR-7 Request object * * @param Container $c * * @return ServerRequestInterface */ $this['request'] = function ($c) { return Request::createFromEnvironment($c->get('environment')); }; } if (!isset($this['environment'])) { /** * This service MUST return a shared instance * of \Slim\Interfaces\Http\EnvironmentInterface. * * @return EnvironmentInterface */ $this['environment'] = function () { return new Environment($_SERVER); }; }
首先看到Request是須要一個environment的,$c->get('environment')生成的是一個Environment對象。其次Environment 是經過$__SERVER構造的對象。html
class Environment extends Collection implements EnvironmentInterface
這裏能夠看出Enviroment是繼承了Collection,全部它的數組形式訪問能夠實現obj[’name’]。同時Environment中實現了EnvironmentInterface接口的mock方法。web
/** * Create new HTTP request with data extracted from the application * Environment object * * @param Environment $environment The Slim application Environment * * @return self */ public static function createFromEnvironment(Environment $environment) { $method = $environment['REQUEST_METHOD']; $uri = Uri::createFromEnvironment($environment); var_dump($uri); $headers = Headers::createFromEnvironment($environment); $cookies = Cookies::parseHeader($headers->get('Cookie', [])); $serverParams = $environment->all(); $body = new RequestBody(); $uploadedFiles = UploadedFile::createFromEnvironment($environment); $request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); if ($method === 'POST' && in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data']) ) { // parsed body must be $_POST $request = $request->withParsedBody($_POST); } return $request; }
/** * Create new Uri from environment. * * @param Environment $env * * @return self */ public static function createFromEnvironment(Environment $env) { // Scheme $isSecure = $env->get('HTTPS'); $scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https'; // Authority: Username and password $username = $env->get('PHP_AUTH_USER', ''); $password = $env->get('PHP_AUTH_PW', ''); // Authority: Host if ($env->has('HTTP_HOST')) { $host = $env->get('HTTP_HOST'); } else { $host = $env->get('SERVER_NAME'); } // Authority: Port $port = (int)$env->get('SERVER_PORT', 80); if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) { $host = $matches[1]; if ($matches[2]) { $port = (int) substr($matches[2], 1); } } else { $pos = strpos($host, ':'); if ($pos !== false) { $port = (int) substr($host, $pos + 1); $host = strstr($host, ':', true); } } // Path //文件名/腳本名 $requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH); //實際上是項目目錄 $requestScriptDir = dirname($requestScriptName); // parse_url() requires a full URL. As we don't extract the domain name or scheme, // we use a stand-in. //就是uri,主機名後面的字符串 $requestUri = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH); $basePath = ''; $virtualPath = $requestUri; if (stripos($requestUri, $requestScriptName) === 0) { $basePath = $requestScriptName; } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) { $basePath = $requestScriptDir; } if ($basePath) { //就是最後文件名或接口名 $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/'); } // Query string $queryString = $env->get('QUERY_STRING', ''); // Fragment $fragment = ''; // Build Uri $uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password); if ($basePath) { $uri = $uri->withBasePath($basePath); } return $uri; }
class Headers extends Collection implements HeadersInterface /** * Create new headers collection with data extracted from * the application Environment object * * @param Environment $environment The Slim application Environment * * @return self */ public static function createFromEnvironment(Environment $environment) { $data = []; foreach ($environment as $key => $value) { $key = strtoupper($key); if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) { if ($key !== 'HTTP_CONTENT_LENGTH') { $data[$key] = $value; } } } return new static($data); } /** * Set HTTP header value * * This method sets a header value. It replaces * any values that may already exist for the header name. * * @param string $key The case-insensitive header name * @param string $value The header value */ public function set($key, $value) { if (!is_array($value)) { $value = [$value]; } parent::set($this->normalizeKey($key), [ 'value' => $value, 'originalKey' => $key ]); } /** * Get HTTP header value * * @param string $key The case-insensitive header name * @param mixed $default The default value if key does not exist * * @return string[] */ public function get($key, $default = null) { if ($this->has($key)) { return parent::get($this->normalizeKey($key))['value']; } return $default; }
class Cookies implements CookiesInterface /** * Parse HTTP request `Cookie:` header and extract * into a PHP associative array. * * @param string $header The raw HTTP request `Cookie:` header * * @return array Associative array of cookie names and values * * @throws InvalidArgumentException if the cookie data cannot be parsed */ public static function parseHeader($header) { if (is_array($header) === true) { $header = isset($header[0]) ? $header[0] : ''; } if (is_string($header) === false) { throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.'); } $header = rtrim($header, "\r\n"); $pieces = preg_split('@\s*[;,]\s*@', $header); $cookies = []; foreach ($pieces as $cookie) { $cookie = explode('=', $cookie, 2); if (count($cookie) === 2) { $key = urldecode($cookie[0]); $value = urldecode($cookie[1]); if (!isset($cookies[$key])) { $cookies[$key] = $value; } } } return $cookies; }
//建立了一個body stream ,stream 指向php://input,這個php://input能夠讀取原始的POST數據 $body = new RequestBody();
實際上是用來獲取原始POST數據的。json
public function __construct( $method, UriInterface $uri, HeadersInterface $headers, array $cookies, array $serverParams, StreamInterface $body, array $uploadedFiles = [] ) { $this->originalMethod = $this->filterMethod($method); $this->uri = $uri; $this->headers = $headers; $this->cookies = $cookies; $this->serverParams = $serverParams; $this->attributes = new Collection(); $this->body = $body; $this->uploadedFiles = $uploadedFiles; if (isset($serverParams['SERVER_PROTOCOL'])) { $this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']); } if (!$this->headers->has('Host') || $this->uri->getHost() !== '') { $this->headers->set('Host', $this->uri->getHost()); } $this->registerMediaTypeParser('application/json', function ($input) { return json_decode($input, true); }); $this->registerMediaTypeParser('application/xml', function ($input) { $backup = libxml_disable_entity_loader(true); $result = simplexml_load_string($input); libxml_disable_entity_loader($backup); return $result; }); $this->registerMediaTypeParser('text/xml', function ($input) { $backup = libxml_disable_entity_loader(true); $result = simplexml_load_string($input); libxml_disable_entity_loader($backup); return $result; }); $this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) { parse_str($input, $data); return $data; }); }
這樣一個request就穩當了,並且含有method、body等數據。數組