Windowsで作る - PHPプログラミングの開発環境
このページへのアクセス 今日: 1 / 昨日: 1 総計: 4146
文書の過去の版を表示しています。
Version 4.5.0
— y2sunlight 2020-09-23
Slim に戻る
関連記事
本章は以下のサイトの Packaged Middleware のセクションを翻訳し若干の補足を加えたのもです。
ルーティングはミドルウェアとして実装されています。まだデフォルトルーターとしてFastRouteを使用していますが、緊密に結合されているわかではありません。別のルーティングライブラリを実装したい場合は、ルーティングインターフェイスの独自の実装を作成することで可能になります。それは、Slimのコンポーネントとルーティングライブラリの間にブリッジを作成する DispatcherInterface、RouteCollectorInterface、RouteParserInterface、および RouteResolverInterface です。もし determineRouteBeforeAppMiddlewareを使用していた場合は、以前の動作を維持するために、run() を呼び出す直前に Middleware\RoutingMiddlewareミドルウェアをアプリケーションに追加する必要があります。
DispatcherInterface
RouteCollectorInterface
RouteParserInterface
RouteResolverInterface
determineRouteBeforeAppMiddleware
run()
Middleware\RoutingMiddleware
<?php use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add Routing Middleware $app->addRoutingMiddleware(); // ... $app->run();
物事はうまくいかない。エラーを予言することはできませんが、予想することはできます。それぞれの Slim Framework アプリケーションには、キャッチされなかったすべてのPHP例外を受け取るエラーハンドラーがあります。このエラーハンドラーは、現在のHTTPリクエスト及びレスポンスオブジェクトも受信します。エラーハンドラは、HTTPクライアントに返される適切なResponseオブジェクトを準備して返す必要があります。
<?php use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); /** * The routing middleware should be added earlier than the ErrorMiddleware * Otherwise exceptions thrown from it will not be handled by the middleware */ $app->addRoutingMiddleware(); /** * @param bool $displayErrorDetails -> Should be set to false in production * @param bool $logErrors -> Parameter is passed to the default ErrorHandler * @param bool $logErrorDetails -> Display error details in error log * which can be replaced by a callable of your choice. * @param \Psr\Log\LoggerInterface $logger -> Optional PSR-3 logger to receive errors * * Note: This middleware should be added last. It will not handle any exceptions/errors * for middleware added after it. */ $errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger); // ... $app->run();
あらゆるタイプの Exception または Throwable のカスタムハンドラーをマップできるようになります。
<?php use Psr\Http\Message\ServerRequestInterface; use Psr\Log\LoggerInterface; use Slim\Factory\AppFactory; use Slim\Psr7\Response; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add Routing Middleware $app->addRoutingMiddleware(); // Define Custom Error Handler $customErrorHandler = function ( ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails, ?LoggerInterface $logger = null ) use ($app) { $logger->error($exception->getMessage()); $payload = ['error' => $exception->getMessage()]; $response = $app->getResponseFactory()->createResponse(); $response->getBody()->write( json_encode($payload, JSON_UNESCAPED_UNICODE) ); return $response; }; // Add Error Middleware $errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger); $errorMiddleware->setDefaultErrorHandler($customErrorHandler); // ... $app->run();
Slimに同梱されているデフォルトの ErrorHandler にカスタムエラーロギングをパイプする場合には、2つの方法があります。
ErrorHandler
最初の方法では、ErrorHandler を拡張し、logError() メソッドをスタブ化するだけです。
logError()
<?php namespace MyApp\Handlers; use Slim\Handlers\ErrorHandler; class MyErrorHandler extends ErrorHandler { protected function logError(string $error): void { // Insert custom error logging function. } }
<?php use MyApp\Handlers\MyErrorHandler; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add Routing Middleware $app->addRoutingMiddleware(); // Instantiate Your Custom Error Handler $myErrorHandler = new MyErrorHandler($app->getCallableResolver(), $app->getResponseFactory()); // Add Error Middleware $errorMiddleware = $app->addErrorMiddleware(true, true, true); $errorMiddleware->setDefaultErrorHandler($myErrorHandler); // ... $app->run();
2番目の方法では、人気のある Monolog ライブラリからのものなど、PSR-3 規約に準拠するロガーを提供できます。
<?php use MyApp\Handlers\MyErrorHandler; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add Routing Middleware $app->addRoutingMiddleware(); // Instantiate Logger // $logger = ... // Add Error Middleware with Logger $errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger); // ... $app->run();
レンダリングは最終的にエラー処理から切り離されています。それでもコンテンツタイプを検出し、ErrorRenderers の助けを借りて適切にレンダリングします。 コアの ErrorHandler は、完全にリファクタリングされた AbstractErrorHandler クラスを拡張します。デフォルトでは、サポートされているコンテンツタイプに合わせた ErrorRenderer が呼び出されます。コアの ErrorHandler は、次のコンテンツタイプのレンダラーを定義します。
ErrorRenderers
AbstractErrorHandler
ErrorRenderer
どのコンテンツタイプでも、独自のエラーレンダラーを登録できます。従って、最初に \Slim\Interfaces\ErrorRendererInterface を実装する新しいエラーレンダラーを定義します。
\Slim\Interfaces\ErrorRendererInterface
<?php use Slim\Interfaces\ErrorRendererInterface; class MyCustomErrorRenderer implements ErrorRendererInterface { public function __invoke(Throwable $exception, bool $displayErrorDetails): string { return 'My awesome format'; } }
次に、そのエラーレンダラーをコアエラーハンドラーに登録します。以下の例では、text/html コンテンツタイプに使用されるレンダラーを登録しています。
text/html
<?php use MyApp\Handlers\MyErrorHandler; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add Routing Middleware $app->addRoutingMiddleware(); // Add Error Middleware $errorMiddleware = $app->addErrorMiddleware(true, true, true); // Get the default error handler and register my custom error renderer. $errorHandler = $errorMiddleware->getDefaultErrorHandler(); $errorHandler->registerErrorRenderer('text/html', MyCustomErrorRenderer::class); // ... $app->run();
デフォルトでは、エラーハンドラーは、リクエストの Accept ヘッダーを使用してエラーレンダラーの検出を試みます。エラーハンドラーに特定のエラーレンダラーを使用させる必要がある場合は、次のように記述できます。
Accept
$errorHandler->forceContentType('application/json');
アプリケーション内に名前付きHTTP例外を追加しています。これらの例外は、ネイティブなレンダラーでうまく機能します。ネイティブHTMLレンダラーが呼び出されたときに、もう少し見識を与えるために、それぞれに description と title 属性を設定することもできます。
description
title
基本クラス HttpSpecializedException は Exception を拡張し、次のサブクラスが付属しています:
HttpSpecializedException
Exception
Example if you wanted a 504 gateway timeout exception that behaves like the native ones you would do the following:
ベースリポジトリで提供しないと判断した他のレスポンスコードが必要な場合は、HttpSpecializedException クラスを拡張できます。例えば、ネイティブのように動作する504ゲートウェイタイムアウト例外が必要な場合は、次のようにします:
class HttpGatewayTimeoutException extends HttpSpecializedException { protected $code = 504; protected $message = 'Gateway Timeout.'; protected $title = '504 Gateway Timeout'; protected $description = 'Timed out before receiving response from the upstream server.'; }
メソッドオーバライド ミドルウエアを使用すると、X-Http-Method-Override リクエストヘッダーまたはリクエストボディのパラメータ _METHOD を使用して、着信リクエストのメソッドをオーバーライドできます。このミドルウェアは、ルーティングミドルウェアが追加された後に配置する必要があります。
X-Http-Method-Override
_METHOD
<?php use Slim\Factory\AppFactory; use Slim\Middleware\MethodOverrideMiddleware; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Add RoutingMiddleware before we add the MethodOverrideMiddleware so the method is overrode before routing is done $app->addRoutingMiddleware(); // Add MethodOverride middleware $methodOverrideMiddleware = new MethodOverrideMiddleware(); $app->add($methodOverrideMiddleware); // ... $app->run();
出力バッファリング ミドルウェアを使用すると、出力バッファリングの2つのモード(APPEND(デフォルト)と PREPEND モード)を切り替えることができます。APPEND モードでは、既存のレスポンスボディを使用してコンテンツを追加します。PREPEND モードは、新しいレスポンスボディ オブジェクトを作成し、既存のレスポンスボディからの出力の前にコンテンツを追加します。このミドルウェアは、最後に実行されるようにミドルウェアスタックの中央に配置する必要があります。
APPEND
PREPEND
<?php use Slim\Factory\AppFactory; use Slim\Middleware\OutputBufferingMiddleware; use Slim\Psr7\Factory\StreamFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $streamFactory = new StreamFactory(); /** * The two modes available are * OutputBufferingMiddleware::APPEND (default mode) - Appends to existing response body * OutputBufferingMiddleware::PREPEND - Creates entirely new response body */ $mode = OutputBufferingMiddleware::APPEND; $outputBufferingMiddleware = new OutputBufferingMiddleware($streamFactory, $mode); $app->add($outputBufferingMiddleware); // ... $app->run();
It’s very common in web APIs to send data in JSON or XML format. Out of the box, PSR-7 implementations do not support these formats, you have to decode the Request object’s getBody() yourself. As this is a common requirement, Slim 4 provides BodyParsingMiddleware to handle this task.
BodyParsingMiddleware
Web APIでは、JSONまたはXML形式でデータを送信するのが非常に一般的です。箱から出しも、PSR-7の実装はこれらの形式をサポートしていません。リクエストオブジェクトの getBody() を自分でデコードする必要があります。これは一般的な要件であるため、Slim4はこのタスクを処理するための BodyParsingMiddleware を提供します。
getBody()
It’s recommended to put the body parsing middleware before the call to addErrorMiddlware, so that the stack looks like this:
addErrorMiddlwareを呼び出す前に、本体解析ミドルウェアを配置して、スタックが次のようになるようにすることをお勧めします:
<?php use Slim\Factory\AppFactory; require_once __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // Parse json, form data and xml $app->addBodyParsingMiddleware(); $app->addRoutingMiddleware(); $app->addErrorMiddleware(true, true, true); // ... $app->run();
No changes are required to the POST handler because the BodyParsingMiddleware detects that the Content-Type is set to a JSON media type and so places the decoded body into the Request’s parsed body property.
BodyParsingMiddleware は Content-Type が JSON メディアタイプに設定されていることを検出し、デコードされた本文をリクエストの解析された本文プロパティに配置するため、POSTハンドラーを変更する必要はありません。
Content-Type
JSON
For data posted to the website from a browser, you can use the $request’s getParsedBody() method.
ブラウザからウェブサイトに投稿されたデータの場合、$request の getParsedBody() メソッドを使用できます。
getParsedBody()
This will return an array of the posted data.
これにより、投稿されたデータの配列が返されます。
$app->post('/', function (Request $request, Response $response, $args): Response { $data = $request->getParsedBody(); $html = var_export($data, true); $response->getBody()->write($html); return $response; });
application/*
The Content Length Middleware will automatically append a Content-Length header to the response. This is to replace the addContentLengthHeader setting that was removed from Slim 3. This middleware should be placed on the center of the middleware stack so it gets executed last.
Content-Length
addContentLengthHeader
Content Length ミドルウェアは、Content-Length ヘッダーを応答に自動的に追加します。 これは、Slim 3から削除された addContentLengthHeader 設定を置き換えるためのものです。このミドルウェアは、最後に実行されるように、ミドルウェアスタックの中央に配置する必要があります。
<?php use Slim\Factory\AppFactory; use Slim\Middleware\ContentLengthMiddleware; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $contentLengthMiddleware = new ContentLengthMiddleware(); $app->add($contentLengthMiddleware); // ... $app->run();