Laravel5 route, event アノテーション

### annotationは本体から切り離されて、3rdパーティと変更されました。
[アノテーションパッケージ](https://github.com/adamgoose/laravel-annotations)

# Laravel5の状況
本題に入る前に現在の状況ですが、
チェックしている方はご存知の通り Laravel5は2015年1月リリースの可能性が高く、
すぐに情報が古くなる場合もあります
また現時点(2014/12/01)ではβ版はありませんが、
開発版をインストールして5の現時点の状態で使用する事が可能です
手軽に使う分にはそこまで大きく変わりませんが、
**Laravelパッケージ開発者や、コアを熟知している中級者や上級者の方々は、
4よりもさらに便利に、より拡張し易い方向へと変わっています**

それでは、5で追加されたルーティングとイベントのアノテーションを！
# Laravel5 install
インストール方法はいくつかありますが、いつもと同じ方法で開発版をインストールする事が出来ます

```bash
$ composer create-project laravel/laravel プロジェクト名 --prefer-dist dev-develop
```

php artisan serveは削除された様なので、簡単に起動させたい場合は

```bash
$ php -S 127.0.0.1:8000 -t 'public/'
```
と、ビルトインサーバを立ち上げるだけです
![You have arrived.](http://recipes.laravel.jp/images/laravel5-install.png)

実行環境の指定方法が変更されましたので、
プロジェクトルートの `.env.sample`を`.env`にリネームする等してください
中に記述されている`APP_ENV=local`で実行環境を変更する事が出来ます
(もちろんこれまでと同じ方法でも可能です、ソースコードを読んでみてください)

# Laravel5 Router
## スタンダードなrouter
今まで通りルーティングは`routes.php`に記述していくことができます
インストール時にすぐに動く様にいくつかルーティング記述されています
ファサードでの記述ではなくなりましたが、この辺りは後日誰かが書くはず・・！

```php:app/Http/routes.php
$router->get('/', 'WelcomeController@index');
$router->get('/home', 'HomeController@index');
```

$routerは`\Illuminate\Routing\Router`オブジェクトで特に変わりませんが、
サービスプロバイダで自由に色々実装できる様に拡張されました
`app/Providers/RouterServiceProvider.php`がそれです

コントローラーの名前空間はデフォルトで下記の様に記述されています

```php
protected $namespace = 'App\Http\Controllers';
```
に記述する事で省略して記述できますが、特に使わなくてもかまいません
使わない場合はこれまでのgroupでの指定と同じです

```php:app/Http/routes.php
$router->group(['namespace' => 'App\Http\Controllers'], function($router) {
        $router->get('/', 'WelcomeController@index');
        $router->get('/home', 'HomeController@index');
    }
);
```

## アノテーション利用のrouter
ではアノテーションを利用してルーティングを作ってみます
`app/Http/routes.php`に記述したものはコメントアウトしておきます

```bash
$ php artisan route:list
```
何も表示されない事を確認、もし表示されていればcompileされたファイルがあるはずなので、

```bash
$ php artisan clear-compiled
```
または`storage/framework/compiled.php`を削除します

ルーティングで利用可能なアノテーションは
`Illuminate\Routing\Annotations\Annotations`にあります

| アノテーション | 該当するもの           | 対象          |
|:-------------:|:---------------------:|:------------:|
| `@Controller` | $router->controller() | クラス     |
| `@Resource`   | $router->resource()   | クラス    |
| `@Middleware` | filter処理等           | クラス・メソッド     |
| `@Where`      | whenに該当　           | クラス・メソッド     |
| `@Get`        | GET                   | メソッド       |
| `@Post`       | POST                  | メソッド    |
| `@Put`        | PUT                   | メソッド    |
| `@Patch`      | PATCH                 | メソッド    |
| `@Delete`     | DELETE                | メソッド    |
| `@Options`    | OPTIONS               | メソッド    |

### メソッドに記述する例
シンプルなGet, Postなどのを利用してみます

```php:app/Http/Controllers/SampleController.php
namespace App\Http\Controllers;

class SampleController extends Controller
{
    /**
     * @Get("sample")
     * @return string
     */
    public function sample()
    {
        return "sample";
    }
}
```

sampleメソッドをGETの処理で使う様にアノテーションで指定します
URIは`/sample`となります
それから、先ほどの`app/Providers/RouterServiceProvider.php`に次の様に追加します

```php:app/Providers/RouterServiceProvider.php
    protected $scan = [
        'App\Http\Controllers\SampleController'
    ];
```
次にControllerのアノテーションをスキャンして、ルーティングを自動で作成します

```bash
$ php artisan route:scan
```
storage/framework/routes.scanned.phpファイルが作成、または元からある方は追記されます

```php
$router->get('sample', [
    'uses' => 'App\Http\Controllers\SampleController@sample',
    'as' => NULL,
    'middleware' => [],
    'where' => [],
    'domain' => NULL,
]);
```

ブラウザなどからアクセスして`sample`と表示されるか確認してみましょう！
spring frameworkのbeanファイルのルーティング版の様なものですね
なおスキャンをしなくても、
`app/Providers/RouterServiceProvider.php`に下記のプロパティを有効にすると
自動で追加される様になります！

```php
protected $scanWhenLocal = true;
```

他のPost等も基本的には同じです
次にフィルターやルーティングに名前を付けていってみましょう
最初から登録されているフィルター(middleware)は
`app/Http/Kernel.php`にあります　ここでは**auth**を使ってみる事にします
*きっと誰かが詳細書いてくれるはず・・！*

```php
    /**
     * @Get("sample", as="sample", middleware={"auth"})
     * @return string
     */
    public function sample()
    {
        return "sample";
    }
```

再度scanを実行してroute:listで確認してみます
![route:list.png](https://qiita-image-store.s3.amazonaws.com/0/32814/064b71c2-eee8-0b61-6677-8391f596baa3.png)
ブラウザからアクセスすると、ログイン画面に遷移されます(用意されていないのでエラー画面のはず)
middlewareとwhenは配列でいくつでも指定できます

```php
    /**
     * @Get("sample/{id}", as="sample", middleware={"auth"}, where={"id": "[0-9]+"})
     * @param $id
     * @return string
     */
    public function sample($id)
    {
        return "sample";
    }
```

引数を必須として、且つ数字以外は利用できないルーティングの場合はこの様になります
またこれまであったdomainも利用できますので、同じ様に追加するだけで指定が可能です

```php
    /**
     * @Get("sample")
     * @Middleware({"auth"})
     * @param $id
     * @return string
     */
    public function sample($id)
    {
        return "sample";
    }
```

さらにMiddlewareとWhereは個別に記述する事も可能です

### クラスに記述する例
いままでのResourceコントローラーと同様に指定してみます

```php
namespace App\Http\Controllers;

/**
 * @Resource("sample", only={"index"}, names={"index": "index.name"})
 */
class SampleController extends \App\Http\Controllers\Controller
{

    public function index()
    {
        return "sample index";
    }

}
```
URIが`/sample`でそれぞれのメソッドがルーティングに登録されますが、
onlyで**indexのみ利用**する様に指定し、
nameは指定しない場合は**sample**をprefixに自動で付与されますが、
名前を任意で指定しました
さらに`@Controller`アノテーションでprefixを付与させたり、
実行する`domain`を指定します

```php
/**
 * @Resource("sample", only={"index"}, names={"index": "index.name"})
 * @Controller(prefix="api", domain="app")
 * @Middleware({"auth"})
 */
class SampleController extends \App\Http\Controllers\Controller
{

}
```
メソッドにもさらに記述して様々なルーティングを作る事が出来ます
他にも色々あり、自分でアノテーションを追加する事も出来ますが、
まだイベントについても書いてないのでまた次回に・・

## ルーティングを共存
複数人のチームで開発している場合は、アノテーションだけだと分かり辛い場合もあります
開発者の好みによってアノテーション有無の両方のルーティングを混ぜて使う事が出来ますので
routes.phpを削除しなければならないとか、そういう事はありませんが、
アノテーションを使ったルーティングが優先されます
またこれらのルーティングはroute:cacheでキャッシュする事も出来ますが、
書くと長くなるのでこの辺で・・

# Laravel5 event annotation
routerに比べれば遥かにシンプルです
`app/Providers/EventServiceProvider.php`にデフォルトのサービスプロバイダーがあります
routerと同じ様にannotationを利用するので、scanで配列を使います
ファイルはどこに作っても構いませんので、簡単なクラスを作ってみます

```php:app/Listener/SampleListener.php
namespace App\listener;

class SampleListener
{

    /**
     * @hears("accessEvent")
     */
    public function access()
    {
        echo "access";
    }
} 
```

ただ単に文字列を返却するだけのシンプルなeventです
`@hears`でイベント名を付けます
それでは同様にscanにクラスを追加するので
`app/Providers/EventServiceProvider.php`に

```php
class EventServiceProvider extends ServiceProvider
{

    protected $scan = [
        "App\Listener\SampleListener"
    ];

}
```

スキャンコマンドは

```php
$ php artisan event:scan 
```
です
実行後に`event.scanned.php`に追記されているのを確認します
もちろんrouterと同じ様に自動で追記することもできます

```php
$events->listen(array (
  0 => 'accessEvent',
), 'App\listener\SampleListener@access');
```
先ほど利用したcontrollerを利用します

```php
namespace App\Http\Controllers;

use Illuminate\Contracts\Events\Dispatcher;

class SampleController extends Controller
{

    /**
     * @Get("sample")
     * @return string
     */
    public function sample(Dispatcher $event)
    {
        $event->fire('accessEvent');
    }
}
```

折角なのでファサードを使わずにメソッドインジェクションでDispatcherを指定して
`fire`でイベントを起こします
ブラウザからアクセスすると
**access**と表示されているはず！
複数の名前をつける事も出来ますので色々遊ぶ事ができます

```php
    /**
     * @hears({"accessEvent", "sample.event"})
     */
    public function access()
    {
        echo "access";
    }
```

それぞれの機能については実装されているコードに記載されていますので、
色々試してやりやすい実装方法でルーティングなどを作りましょう！