【Laravel】PHPテンプレートの利用

こちらの記事は以下の書籍を参考に執筆しました

- [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)

#ビューについて
本格的なWEBページをHTMLを使って表示内容を記述できる仕組みが必要。
このために用意されているのが「テンプレート」
テンプレートはLaravelの**ビュー(View)**を担当している。
MVCのに基づいたビューは画面表示関連をわかりやすい形で作れるように成なる。

アドレスにアクセスし、コントローラはテンプレートを読み込んで表示するが、ただ単にHTMLコードを表示しているわけではない。
##レンダリングの考え方
レンダリングとはLaravelがテンプレートを読み込んで情報をはめ込む作業のこと。

Laravelでは以下の2つのテンプレートが用意されている。

|手法|説明|
|---|---|
|PHPのソースコードをそのまま使用する方法||
|Blade|Laravel独自|

#PHPテンプレートを作る

ここからは実際にテンプレートを作ってみる。

###テンプレートの作成
以下の手順で作成。
1. テンプレートファイルを**resources**フォルダ内の**views**度言うフォルダの中に作成
2. **hello**フォルダを作成
3. helloフォルダにindex.phpを作成

```php5:index.php
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello/Index</title>
    <style>
    </style>
  </head>
  <body>
    <h1>Index</h1>
    <p>this is a sample page with php-template.</p>
  </body>
</html>
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



`2`に関して、**テンプレートは各コントローラごとにフォルダを用意し、その中にコントローラで使うテンプレートをまとめておくのが一般。**

##ルートの設定でテンプレートを表示
web.phpに追記

```php:web.php
Route::get('hello', function () {
    return view('hello.index');
});
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


その後**/hello**にアクセスすると画面が表示される。

####viewメソッドについて
web.phpでは第2引数のクロージャでviewというメソッドを使用している。
viewは引数にテンプレート名を指定すると、そのテンプレートを読み込んで返す。

```php
view('フォルダ名.ファイル名')
```

ここで単に`view('hello')`とすると、viewsフォルダからhelloろ言うファイルを探してしまう。

**ここでviewは「テンプレートを読み込んでその内容を返す」というわけはない**
viewが返すのはテンプレートのレンダリング結果がコンテンツとして設定されている**Response**インスタンス。
結果として「テンプレートを読み込んでその内容を返す」用に見えるだけで実際はそのような動きではないことに注意。

##コントローラでテンプレートを使う
先のルート情報のクロージャで使ったviewをそのままアクションメソッド内で利用するだけ。

HelloControllweクラスのIndexメソッドを修正

```php5
    public function index()
    {
      return view('hello.index');
    }
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



ルート情報を修正

```php5:web.php
Route::get('hello', 'HelloController@index');
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



/helloにアクセスると同じ結果になる。
**Route::getでviewするか
Route::getで呼び出されたアクションメソッドでviewするかの違い**


##値をテンプレートに渡す
index.phpを修正

```php5:index.php
  <body>
    <h1>Index</h1>
    <p><?= $msg;?></p>
    <p><?= date("Y年n月j日");?></p>
  </body>
```

>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


index.phpテンプレートはPHPスクリプトであるため、PHPが記述できる。
`$msg`に値を渡すためにHelloControllerクラスを修正

```php5
    public function index()
    {
      $data=['msg'=>'これはコントローラから渡されたメッセージ'];
      return view('hello.index',$data);
    }
```

>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


/helloにアクセスすると値が渡されていることがわかる。

###テンプレへの値の受け渡し
先の例ではindexメソッドのviewメソッドを呼び出している。
viewの呼び出しは以下のようにする。

```php5
return view(テンプレ,配列)
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


第2引数には＊＊配列(連想配列)＊＊が渡されている。

今回は`['msg'=>'これはコントローラから渡されたメッセージ']`を渡した。
これは配列の値(これはコントローラから渡されたメッセージ)がキー(msg)という名前の変数としてテンプレで用意される。
このようにviewの第2引数では配列を渡すと、**キーが変数名、値がその変数の値となって渡される。**

##ルートパラメ-タをテンプレに渡す
アクセス時にアドレスに記載した値がそのままテンプレへ表示させるにはどうするか。

これには2つの切り分けをする
- ルートパラメータを受け取る部分
- 値をテンプレに書き出す部分

ルートパラメータを受けるにはアクション引数に仮引数を用意し、Route::getでアドレスにパラメータを追記すればいいのだった。
あとはこれをテンプレに渡して表示するだけ。
実際にやってみる。

```php5:index.php
<body>
    <h1>Index</h1>
    <p><?=$msg;?></p>
    <p>ID=<?=$id;?></p>
  
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


indexメソッドを書き換える

```php5
    public function index($id='zero')
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ',
        'id'=>$id
      ];
      return view('hello.index',$data);
    }
```

>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


```php5:web.php
Route::get('hello/{id?}', 'HelloController@index');
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



これで/hello/userとアクセスすると、ルートパラメータの値が表示されていることが確認できる。

##クエリ文字列の利用
アクセスするアドレスの情報を利用して値を渡す方法のもう一つの方法として、「クエリ文字列」を用いる事ができる。

クエリ文字列はルートパラメ-とは受け取り方が違う。

indexメソッドを書き換える。

```php5
    public function index(Request $request)
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ',
        'id'=>$request->id
      ];
      return view('hello.index',$data);
    }
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



ここであ**Requestインスタンス**を渡している。渡す値は`$request->$id`のようにして引き渡している。

```php5:web.php
Route::get('hello', 'HelloController@index');
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


web.phpはこのように書き換えるが{$id?}が消えている。
ごく一般的なルート情報の記述に戻っている。
そして以下のようにアクセスすると正しく受け取れている。
`/hello/?id=sample`
ここで**?id=sample**のようにしてidというキーにsampleという値をわつぃている。

このようにクエリ文字列を使って渡された値は**$request->キー名**で取り出せる。
キー名とは`/hello/?○=sample`の`○`のところ

#Bladeテンプレ
laravelは独自のBladeテンプレがある。この記述法を書いていく。
##Bladeを使う
PHPスクリプトをそのまま使うのは以下のデメリットが有る

- ちょっと書くだけでいいのに`<?php print ○○;?>`と書かなければならない
- PHPは<>で表示されHTMLを同じ形式で書くがこれが、HTML作成ツールなどで構造が崩れてしまう事がある。
- ページを分割してレイアウトする機能がない
- すべてHTMLとPHPで手作業でレイアウトするしかない

Bladeはいくつかの機能を持っている。

- テンプレを継承して新たなテンプレを作る。
- レイアウトの一部をセクションとしてはめ込むことでレイアウトが作れる。

##テンプレを作る
Bladeのテンプレもresourcesのviewsフォルダの中に作成する。
Bladeテンプレファイルは`〇〇.blade.php`という名前にする。
ここでは`index.blade.php`という名前で作成する。
では記述していく

```php5:index.blade.php
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello/Index</title>
    <style>
    body{font-size:16pt;color:#999;}
    h1{
      font-size: 50pt;text-align: right;color:#f6f6f6;margin:-20px 0px -30px 0px;letter-spacing: -4pt;
    }
    </style>
  </head>
  <body>
    <h1>Blade/Index</h1>
    <p>{{$msg}}</p>
  </body>
</html>

```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


ポイントは`{{$msg}}`と書いているところ。
Bladeでは`{{変数}}`のようにしてテンプレに埋め込む。

##アクションの修正
次にコントローラのアクションメソッドを修正していく

```php5
    public function index()
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ'
      ];
      return view('hello.index',$data);
    }
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


アクションメソッドは変わらない。
web.phpはこのように。

```php5:web.php
Route::get('hello', 'HelloController@index');
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



/helloにアクセスすると正しく表示できている。

###`index.php`と`index.blade.php`
今回アクションメソッドで`view('hello.index',...`としているの`index.blade.php`のほうが実行されている。
LaravelではBladeテンプレがあるとそれが優先して読み込まれる。

##フォームを利用する
フォームを利用してみる
以下のように修正する。

```php5:index.blade.php
  <body>
    <h1>Blade/Index</h1>
    <p>{{$msg}}</p>
    <form action="/hello" method="post">
      @csrf
      <input type="text" name="msg">
      <input type="submit">
    </form>
  </body>
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


ポイントはこれ

```
@csrf
```
**Bladeディレクティブ**といい、テンプレに決まったコードを生成して書き出す。
##CSRF対策について
@csrfはCSRF対策のためのBladeディレクティブ。
CSRFはスクリプトなどから外部からフォームを送信するもので、フォームに大量のコンテンツを送りつけりする。
@csrfは**トークン**というランダムな非表示フィールドとして追加する。
このトークン値が正しいフォームだけを受け入れるようにする。
こうすることで正しいフォームからの送信かどうかを見分けることができる。

**LaravelではCSRF対策がなされていないフォームの送信は例外が発生して受付けられないようになっている。**
そのため、フォームを利用するときは必ず@csrfをフォームに用意しておく必要がある。

##アクションの用意
コントローラアクションを用意する。
ここでは2つの処理を書いていく

- /helloへアクセスしたとき
- フォームを送信したとき

以下のように修正する。

```php5
    public function index()
    {
        $data=[
        'msg'=>'名前を入力'
      ];
        return view('hello.index', $data);
    }
    public function post(Request $request)
    {
        $msg=$request->msg;
        $data=[
        'msg'=>'あなたは'.$msg.'です。'
      ];
        return view('hello.index', $data);
    }
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


indexメソッドは/helloにアクセスしたときの処理。
postメソッドはフォームを送信したときの処理
ここでRequestインスタンスを引数に渡してフォームの内容を取得している。

```php5
$msg=$request->msg;
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


フォームのところに`name="msg"`と指定したのは
`$msg=$request->msg;`で取得するため。

**フォームで送信された値はすべてnameプロパティとして取り出せる。**

##POSTのルート設定
ルート情報を追記する

```php5:web.php
Route::post('hello', 'HelloController@post');
```

>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


POST送信は**Route::post**を設定する。使い方はROoute::getと同じ。

**同じアドレスでもPOST,GETのようにアクセスするメソッドが違えば両方ともに使える。**