PHP Slim 環境構築(4) Autoloaderとソースツリー

# PHP Slim 環境構築(4) Autoloaderとソースツリー

## Introduction

[前回](https://qiita.com/dynamitecoolguy/items/24a7d3c145a5e8e5c045)は、RedisとかMySQLとかPostgreSQLとかをdocker-composeを使って構築しましたが、今回は追加ソースのツリーを構築してみたいと思います。

このあたりはベストプラクティスが良く分かっていないので、自己流です。

## 今回のサンプル

[SlimフレームワークのMiddlewareの説明](http://www.slimframework.com/docs/v4/concepts/middleware.html)の前半部分、単純なMiddlewareの追加を実装してみます。

## ソースツリー

ソースツリーは以下の通りにしました。

```
$(PROJECTROOT)
  /compose
  /src
    /hoge
      /public
        index.php
      /lib
        ExampleAfterMiddleware.php
        ExampleBeforeMiddleware.php
    /vendor
    composer.json
    composer.lock
```

### ExmplaAfterMiddleware.php

処理したコンテンツの後ろに":AFTER"と追加するだけの単純なMiddlewareです。

```php:/src/hoge/lib/ExampleAfterMiddleware.php
<?php

namespace Hoge;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Psr\Http\Message\ResponseInterface as Response;

class ExampleAfterMiddleware
{
    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $response = $handler->handle($request);
        $response->getBody()->write(':AFTER');

        return $response;
    }
}
```

### ExampleBeforeMiddleware.php

処理したコンテンツの前に"BEFORE:"と追加するだけのMiddlewareです。
ExampleAfterMiddlewareと"Response"の型が違うのがちょっと嫌な感じです・・・

```php:/src/hoge/lib/ExampleBeforeMiddleware.php
<?php

namespace Hoge;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class ExampleBeforeMiddleware
{
    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $response = $handler->handle($request);
        $existingContent = (string) $response->getBody();

        $newResponse = new Response();
        $newResponse->getBody()->write('BEFORE:' .  $existingContent);

        return $newResponse;
    }
}
```

## composer.json

composer.json書き換えて云々というのがよくあるタイプの解決方法ですが、今回はcomposerを書き換えない方法を使います。


## index.php

新しく書き換えたHello, Worldのindex.phpです。
ポイントは、require autoload.phpが返してきたClassLoader(Composer\Autoload\ClassLoader)に対して、Psr4名前空間しているところです。

```php:/src/hoge/public/index.php
<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

use Hoge\ExampleAfterMiddleware;
use Hoge\ExampleBeforeMiddleware;

/** @var Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__ . '/../../vendor/autoload.php';
$loader->addPsr4('Hoge\\', __DIR__ . '/../lib');

$app = AppFactory::create();

// Middleware
$app->add(new ExampleBeforeMiddleware());
$app->add(new ExampleAfterMiddleware());

$app->get('/', function (Request $request, Response $response, array $args) {
    $response->getBody()->write('Hello, World!');
    return $response;
});

$app->run();
```

これで、このページにアクセスすると、"BEFORE:Hello, World!:AFTER"と出るはずです。

なお、参考までに呼び出しシーケンスは、以下の通りです。

```
ExampleAfterMiddleware::__invoke
  ExampmleBeforeMiddleware::__invoke
    index.phpで"Hello, World!"が返される
  "BEFORE:Hello, World!"になる
"BEFORE:Hello, World!:AFTER"になる
```

## ここまでのソース

[こちら](https://github.com/dynamitecoolguy/slimtemplate/tree/chapter4)でどうぞ。