Slim app 的路由和中間件給予一個 PSR-7 請求物件,代表網路伺服器接收到的目前 HTTP 請求。請求物件實作 PSR-7 ServerRequestInterface,您可以使用它來檢視和操作 HTTP 請求方法、標頭和主體。
PSR-7 請求物件注入至 Slim 應用程式路由,作為路由回呼的第一個參數,如下所示
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/hello', function (Request $request, Response $response) {
$response->getBody()->write('Hello World');
return $response;
});
$app->run();
PSR-7 請求物件注入至 Slim 應用程式「中間件」,作為中間件可呼叫物件的第一個參數,如下所示
將 PSR-7 請求注入應用程式中間件
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->add(function (Request $request, RequestHandler $handler) {
return $handler->handle($request);
});
// ...define app routes...
$app->run();
每個 HTTP 請求都有一個方法,通常為下列之一
您可以使用 Request 物件方法,適當地命名為 getMethod()
,來檢視 HTTP 請求的方法。
$method = $request->getMethod();
可以偽造或「覆寫」HTTP 請求方法。這很有用,例如,如果您需要模擬使用只支援 GET
或 POST
請求的傳統網路瀏覽器進行的 PUT
請求。
注意: 要啟用請求方法替代,必須在應用程式中注入Method Overriding Middleware。
有兩種方法可以替代 HTTP 請求方法。你可以在 POST
請求主體中包含 METHOD
參數。HTTP 請求必須使用 application/x-www-form-urlencoded
內容類型。
使用 _METHOD 參數替代 HTTP 方法
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 22
data=value&_METHOD=PUT
你也可以使用自訂 X-Http-Method-Override
HTTP 請求標頭替代 HTTP 請求方法。此方式支援任何 HTTP 請求內容類型。
POST /path HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 16
X-Http-Method-Override: PUT
{"data":"value"}
若要擷取與傳入請求環境相關的資料,你將需要使用 getServerParams()
。例如,若要取得單一伺服器參數
$params = $request->getServerParams();
$authorization = $params['HTTP_AUTHORIZATION'] ?? null;
如果請求方法是 POST
而 Content-Type
是 application/x-www-form-urlencoded
或 multipart/form-data
,你可以照下列範例擷取所有 POST
參數
// Get all POST parameters
$params = (array)$request->getParsedBody();
// Get a single POST parameter
$foo = $params['foo'];
每個 HTTP 請求都有 URI,用於識別請求的應用程式資源。HTTP 請求 URI 包含下列幾個部分
http
或 https
)example.com
)80
或 443
)/users/1
)sort=created&dir=asc
)你可以使用 getUri()
方法擷取 PSR-7 請求物件的 URI 物件。
$uri = $request->getUri();
PSR-7 請求物件的 URI 本身是一個物件,提供下列方法以檢查 HTTP 請求 URL 的部分
a=1&b=2
)你可以在請求物件上使用 getQueryParams()
,以關聯式陣列取得查詢參數。
getQueryParams()
方法會以關聯式陣列擷取 HTTP 請求 URI 中的所有查詢參數。
如果沒有查詢參數,它會傳回一個空陣列。
在內部,此方法使用 parse_str 將查詢字串解析為一個陣列。
用法
// URL: https://example.com/search?key1=value1&key2=value2
$queryParams = $request->getQueryParams();
Array
(
[key1] => value1
[key2] => value2
)
要從查詢參數陣列讀取單一值,則可以使用參數的名稱作為金鑰。
// Output: value1
$key1 = $queryParams['key1'] ?? null;
// Output: value2
$key2 = $queryParams['key2'] ?? null;
// Output: null
$key3 = $queryParams['key3'] ?? null;
注意: ?? null
可確保如果查詢參數不存在,則會傳回 null
,而不是導致警告。
每個 HTTP 要求都有標頭。這些是描述 HTTP 要求的元資料,但不會顯示在要求的主體中。Slim 的 PSR-7 要求物件提供多種方法來檢查其標頭。
您可以使用 PSR-7 要求物件的 getHeaders()
方法,以關聯式陣列的形式擷取所有 HTTP 要求標頭。產生的關聯式陣列的金鑰是標頭名稱,而其值是一個數字陣列,其中包含各自標頭名稱的字串值。
$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
echo $name . ": " . implode(", ", $values);
}
您可以使用 PSR-7 要求物件的 getHeader($name)
方法取得單一標頭的值。這會傳回給定標頭名稱的值陣列。請記住,單一 HTTP 標頭可能會有多個值!
取得特定 HTTP 標頭的值
$headerValueArray = $request->getHeader('Accept');
您也可以使用 PSR-7 要求物件的 getHeaderLine($name)
方法,以特定標頭的所有值取得逗號分隔字串。與 getHeader($name)
方法不同,此方法傳回一個逗號分隔字串。
以逗號分隔字串的形式取得單一標頭的值
$headerValueString = $request->getHeaderLine('Accept');
您可以使用 PSR-7 要求物件的 hasHeader($name)
方法來測試是否存在標頭。
if ($request->hasHeader('Accept')) {
// Do something
}
您可以使用要求物件的 getHeaderLine()
方法,查看標頭 X-Requested-With
是否是 XMLHttpRequest
來偵測 XHR 要求。
XHR 要求範例
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 7
X-Requested-With: XMLHttpRequest
foo=bar
if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {
// Do something
}
可以使用要求物件的 getHeaderLine()
方法擷取 HTTP 要求內容類型。
$contentType = $request->getHeaderLine('Content-Type');
可以使用要求物件的 getHeaderLine()
方法擷取 HTTP 要求內容長度。
$length = $request->getHeaderLine('Content-Length');
每個 HTTP 要求都有主體。如果您建立使用 JSON 或 XML 資料的 Slim 應用程式,可以使用 PSR-7 要求物件的 getParsedBody()
方法,將 HTTP 要求主體剖析成原生 PHP 格式。請注意,主體剖析會因 PSR-7 的實作而異。
您可能需要實作中間件以剖析傳入的輸入,具體視您已安裝的 PSR-7 實作而定。以下是剖析傳入的 JSON
輸入的範例
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
class JsonBodyParserMiddleware implements MiddlewareInterface
{
public function process(Request $request, RequestHandler $handler): Response
{
$contentType = $request->getHeaderLine('Content-Type');
if (strstr($contentType, 'application/json')) {
$contents = json_decode(file_get_contents('php://input'), true);
if (json_last_error() === JSON_ERROR_NONE) {
$request = $request->withParsedBody($contents);
}
}
return $handler->handle($request);
}
}
將 HTTP 要求內文剖析為原生的 PHP 格式
$parsedBody = $request->getParsedBody();
技術上來說,PSR-7 Request 物件會將 HTTP 要求內文表示為 Psr\Http\Message\StreamInterface
的執行個體。您可以透過 PSR-7 Request 物件的 getBody()
方法取得 HTTP 要求內文的 StreamInterface
執行個體。如果傳入的 HTTP 要求大小不明,或太大以致無法使用現有記憶體,則建議使用 getBody()
方法。
取得 HTTP 要求內文
$body = $request->getBody();
結果的 Psr\Http\Message\StreamInterface
執行個體會提供以下方法,以讀取並反覆運算其底層的 PHP 資源
。
上傳至 $_FILES
中的檔案,可透過 Request 物件的 getUploadedFiles()
方法取得。這會傳回一個陣列,其金鑰為 input
元素的名稱。
取得上傳的檔案
$files = $request->getUploadedFiles();
在 $files
陣列中的每個物件都是 Psr\Http\Message\UploadedFileInterface
的執行個體,支援以下方法
請參閱食譜,了解如何使用 POST 檔案上傳檔案。
透過 PSR-7,您可以將物件/數值注入 request 物件以進行進一步處理。在您的應用程式中,中間件常常需要將資訊傳遞給您的路由封閉,而這麼做的方式是透過屬性將其加入 request 物件。
範例,設定您的 request 物件上的數值。
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
$app->add(function (Request $request, RequestHandler $handler) {
// Add the session storage to your request as [READ-ONLY]
$request = $request->withAttribute('session', $_SESSION);
return $handler->handle($request);
});
範例,如何擷取數值。
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app->get('/test', function (Request $request, Response $response) {
// Get the session from the request
$session = $request->getAttribute('session');
$response->getBody()->write('Yay, ' . $session['name']);
return $response;
});
request 物件也有批次函式。 $request->getAttributes()
和 $request->withAttributes()
。