lumen setup guide 


せっかくlumen使うならからディレクトリから構築してしまいたい。
でも空から仕上げるのは何かと面倒だったり。

セットアップに必要な手順を順番に列挙していく。

## composer 

````
composer require laravel/lumen
composer require illuminate/redis # redisを使用する場合
````

ドキュメントには`redis`を使用する場合に`predis/predis`を使用するよう記述してある箇所が多いが、それだとServiceProviderがロードできなくて詰む。

`illuminate/redis`を入れとくと`predis`も勝手に入る。

## ディレクトリ構成

Application を拡張しない場合には、基本の構成に沿っておくのが楽そう

````
mkdir app bootstrap storage storage/logs
mkdir config # configを拡張する場合
mkdir database/migrations database/seeds　# migration 系を使用する場合
mkdir resources resources/views # viewを拡張する場合
```` 

## bootstrapの記述

`bootstrap/app.php`を作成して起動ファイルを作成していく。
`public/index.php` よりもbootstrapを作って置いて`index.php`で読み込むほうが、ディレクトリを落としたい時とかに、Applicationクラス起動時のディレクトリ階層が固定されるので、楽。

````
<?php

require __DIR__."/../vendor/autoload.php";

$app = new \Laravel\Lumen\Application(__DIR__."/../");

//　何かしらの設定

return $app;
````

`public/index.php`の記述はこうなる。

````
<?php
$app = require __DIR__ . "/../bootstrap/app.php";

$app->run();
````

コマンドを使用する場合には`artisan`ファイルを作成する。

````
#!/usr/bin/env php
<?php
$app = require __DIR__.'/bootstrap/app.php';

use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Illuminate\Console\Scheduling\Schedule;


class Kernel extends \Laravel\Lumen\Console\Kernel
{
    protected $commands = [
        //
    ];

    protected function schedule(Schedule $schedule)
    {
        //
    }
}




exit((new Kernel($app))->handle(new ArgvInput, new ConsoleOutput));

````

artisanのやり方は諸説あるだろうけど、いちいちKernelを中に保つ必要はないと個人的には思っている。Commandsが一つ深くなる理由もいまいち納得出来ない。

### 基本的な設定

````
Dotenv::load(__DIR__.'/../');
// $app->withEloquent(); # Eloquent使うなら
// $app->withFacades();  # Facade使うなら
````

個人的にはEloquentもFacadeも使わないので切ってもいい。

### インターフェイスの実装

````
$app->singleton('Illuminate\Contracts\Debug\ExceptionHandler',Hoge::class);

$app->singleton('Illuminate\Contracts\Console\Kernel',Piyo::class);
````

デフォルトで必要とされているのは上記２つ。
↑で記述したartisan 内でKernelを実装する方法を取れば下はいらない。

### ミドルウェアの実装

````
 $app->middleware([
//      'Illuminate\Cookie\Middleware\EncryptCookies',
//      'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
//      'Illuminate\Session\Middleware\StartSession',
//      'Illuminate\View\Middleware\ShareErrorsFromSession',
//      'Laravel\Lumen\Http\Middleware\VerifyCsrfToken',
 ]);

````

## heroku で使用するカスタマイズ

PaaSでherokuを使用する事が多いのでその辺りの設定をば

### database の設定

````
cp vendor/laravel/lumen-framework/config/database config/database
````

````
# config/database.php 
$clearDB = parse_url(getenv('CLEARDB_DATABASE_URL'));

// 中略

        'mysql' => [
            'driver'    => 'mysql',
            'host'      => env('DB_HOST', $clearDB["host"]),
            'port'      => env('DB_PORT', 3306),
            'database'  => env('DB_DATABASE', substr($clearDB["path"],1)),
            'username'  => env('DB_USERNAME', $clearDB["user"]),
            'password'  => env('DB_PASSWORD', $clearDB["pass"]),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => env('DB_PREFIX', ''),
            'timezone'  => env('DB_TIMEZONE', '+00:00'),
            'strict'    => false,
        ],
````

````
# config/database.php 
$redisUrl = parse_url(getenv('REDISTOGO_URL'));

// 中略

    'redis' => [

        'cluster' => env('REDIS_CLUSTER', false),

        'default' => [
            'host' => $redisUrl['host'],
            'port' => $redisUrl['port'],
            'database' => 0,
            'password' => $redisUrl['pass'],
    ],
````

Herokuのaddon configなどはパースして別の変数に落としこむこともできるが、
アプリ側でパースするよう記述しておくと、forkした時とかに設定しなおさなくていいので楽。

### ログの設定

herokuのログは標準出力に垂れ流す感じのイメージなので、Monologのハンドラでコレを設定する。デフォルトのstorage/logsに吐き出すものは、正直使い物にならないので無視する。

設定は`Application::getMonologHandler`を上書きして行う。

````


class Application extends Lumen{

    /**
     * Get the Monolog handler for the application.
     *
     * @return \Monolog\Handler\AbstractHandler
     */
    protected function getMonologHandler()
    {
        return (new StreamHandler('php://stdout', Logger::DEBUG))
            ->setFormatter(new LineFormatter(null, null, true, true));
    }
}
````