昨日、index.php に get(pattern, clouser) を追加することで、ローカル URL を指定された処理クラスにルーティングして、処理後 (ここではデータベースに保存するという意味です)、応答を返すことができると言いました。デバイスに表示される閲覧時。
昨日残った最後の疑問は、 アプリのコンテナに独自のキーを追加できますか? 今日も解決されていません。
今日の作業は、処理完了後にログを記録するミドルウェアを追加することです。
Slim3.0ではSlim2のように各MiddlewareにApplicationを追加しなくなったため、Middleware内でAppデータを取得することが困難になると同時に、コンテナにキーを追加する問題も解決されていません。したがって、私のアイデアは次のとおりです:
1. APP クラスはミドルウェアを追加してルーターを起動するためにのみ使用されます
2. 関連するビジネス処理のためにルーターをモジュールとして登録します
3. モジュールにはロギングを実装するクラスが含まれます。
4. ミドルウェアで対応するクラスを指定します。
実はまだ疑問があるんですが、ミドルウェアの __invoke() メソッドはいつ実行されるのかということです。コードを辿ってみると、ミドルウェアを追加する際に、次のようなコードがあることが分かりました:
protected function addMiddleware(callable $callable) { echo 'add middle ware'; if ($this->middlewareLock) { throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); } if (is_null($this->stack)) { $this->seedMiddlewareStack(); } $next = $this->stack->top(); $this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) { $result = call_user_func($callable, $req, $res, $next); if ($result instanceof ResponseInterface === false) { throw new UnexpectedValueException( 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' ); } return $result; }; return $this; }
このコードで最も重要なのは、次の 2 つの文です:
$next = $this->stack- >top();
$this->stack[] = function();
この stack[] はミドルウェアスタックに追加されますが、この関数 () が重要なもので、いわゆる
依存性の注入。 興味深いのは、関数全体が実行されるのではなく、実行される場合はミドルウェアの __invoke() メソッドが実行されることです。いつ実行するか? 論理的に言えば、コード内の app->run() で呼び出される現在のミドルウェア シーケンスに到達したときに実行されます。コードでわかるように、中間スタックの最上位要素を呼び出します。
public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res) { if (is_null($this->stack)) { $this->seedMiddlewareStack(); } /** @var callable $start */ $start = $this->stack->top(); $this->middlewareLock = true; $resp = $start($req, $res); $this->middlewareLock = false; return $resp; }
$start($req,$res) のときに、匿名関数 function が実行され、カスタム ミドルウェアの __invoke() が実行されました。
これは
Dependency Injectionの概念であるはずですが、今はよく理解できていないので、後でよく勉強する必要があります。
これでソースコードはある程度理解できました。上記の4つの考え方を踏まえて、設計のポイントは次の2つです:
1. Moduleを本体とし、そのモジュールにLogやDBなどの必要なライブラリを追加します
2.ミドルウェアのモジュール、モジュールを呼び出す方法はログを書き込むことです
モジュールにログとDBを追加するのは簡単ですが、ミドルウェアをモジュールよりも先に登録して、それに関連付けられたものが使えないのが原因です。登録時に module が NULL になっているため、後で実行するとモジュールが見つからず、さまざまなメソッドが存在しないというエラーが発生します。
$app->add(Example\MiddleWare\MyMiddleware::instance());$app->post('/homepage', function ($request, $response, $args) use ($app) { Example\Module\Replace::instance($request,$response)->excute(); return $response;});
この場合、まずモジュールを存在させてモジュールをインスタンス化し、エラーが報告されないようにモジュールとミドルウェアのコードを次のように変更します。
/**** Module**/public function init($request,$response){ $this->request = $request; $this->response = $response; $this->excute();}public abstract function excute();
そしてindex.phpにミドルウェアとルーターを追加すると以下のようなコードになります:
/*** Middleware*/ self::$middleWare = is_null(self::$middleWare)?new MyMiddleware($module):self::$middleWare; return self::$middleWare;}public function __construct($module){ $this->module = $module;}
このようにしてMiddlewareでLogWriteを完了する機能が実現されるのですが、問題はModuleとMiddlewareの指定です。他のルータを登録するときにモジュールを動的に変更できない場合。これは良くない!
他にもっと良い方法はありますか? フレームワークには匿名関数(Closer)がたくさんあります。クローザーの解決策はありますか?
ミドルウェアでモジュールを動的に指定する問題を解決する必要があります。または、アプリで何ができるのかわかりません。