Capter2　ルーティングとコントローラー

# 2-1　ルーティング

## トップページの記述について

ルーティングに関する記述は「routes」フォルダで行う。

```web.php
Route::get('/', function () {
    return view('welcome');
});
```

上記の記述はトップページにアクセスした時、
「welcome」というテンプレートを返すといいう記述です。
＊VIEWという関数で渡されるテンプレートは、
　「resources」の「views」に格納されている。

## 下層ページへの記述について

下層ページ「/hello」へルーティングさせたい場合、
下記のように記述する

```web.php
Route::get('/hello', function () {
  return '<html><body><h1>hello</h1><p>This is sample page.</p></body></html>';
});

```

## ヒアドキュメントの利用

```web.php
$html = <<<EOF

<html>
<head>
<title>Hello</title>
<style>
body {
  font-size: 16pt;
  color: #999;
}
h1 {
  font-size: 100pt;
  text-align: right;
  color: #eee;
  margin: -40px 0px -50px 0px;
}
</style>
</head>
  <body>
    <h1>hello</h1>
    <p>This is sample page.</p>
   </body>
 </html>

EOF;

Route::get('/hello', function () use ($html) {
  return $html;
});
```

$html変数に長い変数を入れる場合、
ヒアドキュメントを利用することで容易に格納が可能になります。
（＊ソースコードの青字部分）

# ルートパラメーターの利用

```web.php
Route::get('/hello/{msg}', function ($msg) {

  $html = <<<EOF

  <html>
  <head>
  <title>Hello</title>
  <style>
  body {
    font-size: 16pt;
    color: #999;
  }
  h1 {
    font-size: 100pt;
    text-align: right;
    color: #eee;
    margin: -40px 0px -50px 0px;
  }
  </style>
  </head>
    <body>
      <h1>hello</h1>
      <p>{$msg}</p>
      <p>This is sample page.</p>
     </body>
   </html>

EOF;

  return $html;
});
```

上記の記述をすると、
「/hello/test」のアドレスに遷移すると、
　**パラメーターとして「test」が渡され、本文にtestと表示させる**ことができる。

# 必須パラメータと任意パラメータ

```web.php
Route::get('/hello/{msg?}', function ($msg='no message') {

  $html = <<<EOF

  <html>
  <head>
  <title>Hello</title>
  <style>
  body {
    font-size: 16pt;
    color: #999;
  }
  h1 {
    font-size: 100pt;
    text-align: right;
    color: #eee;
    margin: -40px 0px -50px 0px;
  }
  </style>
  </head>
    <body>
      <h1>hello</h1>
      <p>{$msg}</p>
      <p>This is sample page.</p>
     </body>
   </html>

EOF;

  return $html;
});

```

`Route::get('/hello/{msg?}', function ($msg='no message') {`
{msg}の後に？をつけることで、任意パラメータであることを指定し、
引数に`$msg='no message'`とすることで、
「/hello」に遷移した場合のパラメータ初期値に「no message」を代入している。

# 2-2　コントローラ

## コントローラの新規作成

コマンドプロンプトで以下のコマンドを叩くと、
「HelloController」というコントローラを「app」>「Https」>「Controllers」に新規作成する。
```command
php artisan make:controller HelloController
```

```HelloController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HelloController extends Controller
{
    //
}
```

**名前空間**はフォルダの階層のような物で、
HelloController.phpは`App\Http\Controllers`という名前空間に配置されていることを、
`namespace App\Http\Controllers;`で定義されています。

**useによるクラスのインポート**
`use Illuminate\Http\Request;`
「Illuminate\Http」パッケージに用意されている「Request」を使える状態にするための定義付けしている。

**クラスの定義**
`class HelloController extends Controller {    //    }`
Controllerクラスを継承して、HelloControllerクラスを定義付けしている。


## アクションを追加する

HelloControllerにindexというアクションを追加して、
HelloControllerのindexアクションに「/hello」のルートを割り当てる。

### コントローラーにアクションを追加
```HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function index() {

      return <<<EOF
      
          <html>
          <head>
          <title>Hello/Index</title>
          <style>
          body {
            font-size: 16pt;
            color: #999;
          }
          h1 {
            font-size: 100pt;
            text-align: right;
            color: #eee;
            margin: -40px 0px -50px 0px;
          }
          </style>
          </head>
            <body>
              <h1>Index</h1>
              <p>これはHelloコントローラのindexアクションです。</p>
             </body>
           </html>

EOF;

    }
}
```
### アクションにルートを割り当てる
```web.php
Route::get('/hello','HelloController@index');
```

上記の記述だと、「コントローラが存在しない」とエラーが出るため、
下の記事を参考に記述を変更した。

https://qiita.com/norichintnk/items/34a04cd17bfe4014313a

```web.php
Route::get('/hello','App\Http\Controllers\HelloController@index');
```
すると、記事とおり表示されるようにはなったが、
`use Illuminate\Http\Request;`が機能していないようなので、
適切な恒久対応とは言いずらい。（一旦これで進めてみる）

## ルートパラメータの利用

idとpassという二つの任意パラメータを与え、
indexアクションに引数を指定し、ルート情報の修正をする。

```HelloController.php
class HelloController extends Controller
{
    public function index($id='noname',$pass='unknown') {

  　　　　　　　　　　　　　　　　　　　　　***中身は省略***

    }
}

```
```web.php
Route::get('/hello/{id?}/{pass?}','App\Http\Controllers\HelloController@index');
```

上記の修正をすることで、「/hello/yamada/password」とアドレスでアクセスすると、
画面にパラメーター値（ID: yamada, PASS: password）が表示される。

## 複数アクションの利用

HelloControllerにindex、otherの二つのアクションを用意し、
「hello」にアクセスされたときに、indexアクション
「hello/other」にアクセスされたときに、otherアクション　を割り当てる。

### 複数アクションの追加

```HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

global $head, $style, $body, $end;

$head = '<html><head>';
$style = <<<EOF
<style>
body {
  font-size: 16pt;
  color: #999;
 }
 h1 {
  font-size: 100pt;
  text-align: right;
  color: #eee;
  margin: -40px 0px -50px 0px;
}
</style>
EOF;
$body = '</head><body>';
$end = '</body></html>';

function tag($tag,$txt) {
  return "<{$tag}>" .$txt . "</{$tag}>";
}

class HelloController extends Controller
{
    public function index() {

        global $head, $style, $body, $end;

        $html = $head . tag('title','Hello/Index') . $style . $body . tag('h1','Index') .
          tag('p','This is Index page') . '<a href="/hello/other">go to Other page</a>' . $end;
        return $html;

    }

    public function other() {

      global $head, $style, $body, $end;

      $html = $head . tag('title', 'Hello/Other') . $style . $body . tag('h1', 'Other') .
        tag('p', 'This is Other page') . $end;
      return $html;

    }
}
```

### アクションのルート割り当て
```web.php
Route::get('hello','App\Http\Controllers\HelloController@index');
Route::get('hello/other','App\Http\Controllers\HelloController@other');
```

## シングルアクション化

### シングルアクションの基本形

`__invoke()`というPHPのクラスに用意されている「マジックメソッド」を使用します。

```controller.php
class *コントローラー名* extends Controller
{
    public function __invoke() {
       **アクション処理**
    }
}
```
シングルアクションのコントローラの場合、ルート情報はコントローラー名のみ指定します。
```web.php
Route::get('hello','App\Http\Controllers\*コントローラー名*');
```

### HelloControllerをシングルアクション化する

```HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function __invoke() {

        return <<<EOF
        
            <html>
            <head>
            <title>Hello/Index</title>
            <style>
            body {
              font-size: 16pt;
              color: #999;
            }
            h1 {
              font-size: 100pt;
              text-align: right;
              color: #eee;
              margin: -40px 0px -50px 0px;
            }
            </style>
            </head>
              <body>
                <h1>Index</h1>
                <p>これはHelloコントローラのindexアクションです。</p>
               </body>
             </html>
EOF;
    }
}

```

```web.php
Route::get('hello','App\Http\Controllers\HelloController');
```

## リクエストとレスポンス

### RequestクラスとResponseクラスを使えるようにする

```HelloController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index(Request $request, Response $response) {

        return <<<EOF
        
            <html>
            <head>
            <title>Hello/Index</title>
            <style>
            body {
              font-size: 16pt;
              color: #999;
            }
            h1 {
              font-size: 120pt;
              text-align: right;
              color: #fafafa;
              margin: -50px 0px -120px 0px;
            }
            </style>
            </head>
              <body>
                <h1>Hello</h1>
                <h3>Request</h3>
                <pre>{$request}</pre>
                <h3>Response</h3>
                <pre>{$response}</pre>
               </body>
             </html>
EOF;
        $response->setContent($html);
        return $response;

    }
}
```
`public function index(Request $request, Response $response) {`
上記のようにファンクションの引数に追加するだけで、
インスタンスが用意され使えるようになります。


### アクションを指定
```web.php
Route::get('hello','App\Http\Controllers\HelloController@index');
```

#### 主なメソッド

Request
`$request->url();`　：アクセスしたURLを返す
`$request->fullUrl();`　：アクセスしたアドレスを完全な形で返す
`$request->path();`　：ドメイン下のパス部分だけ返す
`$this->status();`　：ステータスコード、表示コンテンツの設定を返す

Response
`$this->content();`　：コンテンツの取得
`$this->setContent(*値*);`　：引数の「*値*」にコンテンツを変更する

RequestやResponseのように、
アクションメソッドに引数を追加するとサービスコンテナによって対応するクラスのインスタンスがその引数に渡され、利用できるようなる機能を **「メソッドインジェクション」** という。