こちらの記事は以下の書籍を参考に執筆しました
ビューについて
本格的なWEBページをHTMLを使って表示内容を記述できる仕組みが必要。
このために用意されているのが「テンプレート」
テンプレートはLaravelの**ビュー(View)**を担当している。
MVCのに基づいたビューは画面表示関連をわかりやすい形で作れるように成なる。
アドレスにアクセスし、コントローラはテンプレートを読み込んで表示するが、ただ単にHTMLコードを表示しているわけではない。
レンダリングの考え方
レンダリングとはLaravelがテンプレートを読み込んで情報をはめ込む作業のこと。
Laravelでは以下の2つのテンプレートが用意されている。
手法 | 説明 |
---|---|
PHPのソースコードをそのまま使用する方法 | |
Blade | Laravel独自 |
PHPテンプレートを作る
ここからは実際にテンプレートを作ってみる。
テンプレートの作成
以下の手順で作成。
- テンプレートファイルをresourcesフォルダ内のviews度言うフォルダの中に作成
- helloフォルダを作成
- helloフォルダに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>
2
に関して、テンプレートは各コントローラごとにフォルダを用意し、その中にコントローラで使うテンプレートをまとめておくのが一般。
ルートの設定でテンプレートを表示
web.phpに追記
Route::get('hello', function () {
return view('hello.index');
});
その後**/hello**にアクセスすると画面が表示される。
viewメソッドについて
web.phpでは第2引数のクロージャでviewというメソッドを使用している。
viewは引数にテンプレート名を指定すると、そのテンプレートを読み込んで返す。
view('フォルダ名.ファイル名')
ここで単にview('hello')
とすると、viewsフォルダからhelloろ言うファイルを探してしまう。
ここでviewは「テンプレートを読み込んでその内容を返す」というわけはない
viewが返すのはテンプレートのレンダリング結果がコンテンツとして設定されているResponseインスタンス。
結果として「テンプレートを読み込んでその内容を返す」用に見えるだけで実際はそのような動きではないことに注意。
コントローラでテンプレートを使う
先のルート情報のクロージャで使ったviewをそのままアクションメソッド内で利用するだけ。
HelloControllweクラスのIndexメソッドを修正
public function index()
{
return view('hello.index');
}
ルート情報を修正
Route::get('hello', 'HelloController@index');
/helloにアクセスると同じ結果になる。
Route::getでviewするか
Route::getで呼び出されたアクションメソッドでviewするかの違い
値をテンプレートに渡す
index.phpを修正
<body>
<h1>Index</h1>
<p><?= $msg;?></p>
<p><?= date("Y年n月j日");?></p>
</body>
index.phpテンプレートはPHPスクリプトであるため、PHPが記述できる。
$msg
に値を渡すためにHelloControllerクラスを修正
public function index()
{
$data=['msg'=>'これはコントローラから渡されたメッセージ'];
return view('hello.index',$data);
}
/helloにアクセスすると値が渡されていることがわかる。
テンプレへの値の受け渡し
先の例ではindexメソッドのviewメソッドを呼び出している。
viewの呼び出しは以下のようにする。
return view(テンプレ,配列)
第2引数には**配列(連想配列)**が渡されている。
今回は['msg'=>'これはコントローラから渡されたメッセージ']
を渡した。
これは配列の値(これはコントローラから渡されたメッセージ)がキー(msg)という名前の変数としてテンプレで用意される。
このようにviewの第2引数では配列を渡すと、キーが変数名、値がその変数の値となって渡される。
ルートパラメ-タをテンプレに渡す
アクセス時にアドレスに記載した値がそのままテンプレへ表示させるにはどうするか。
これには2つの切り分けをする
- ルートパラメータを受け取る部分
- 値をテンプレに書き出す部分
ルートパラメータを受けるにはアクション引数に仮引数を用意し、Route::getでアドレスにパラメータを追記すればいいのだった。
あとはこれをテンプレに渡して表示するだけ。
実際にやってみる。
<body>
<h1>Index</h1>
<p><?=$msg;?></p>
<p>ID=<?=$id;?></p>
indexメソッドを書き換える
public function index($id='zero')
{
$data=[
'msg'=>'これはコントローラから渡されたメッセージ',
'id'=>$id
];
return view('hello.index',$data);
}
Route::get('hello/{id?}', 'HelloController@index');
これで/hello/userとアクセスすると、ルートパラメータの値が表示されていることが確認できる。
クエリ文字列の利用
アクセスするアドレスの情報を利用して値を渡す方法のもう一つの方法として、「クエリ文字列」を用いる事ができる。
クエリ文字列はルートパラメ-とは受け取り方が違う。
indexメソッドを書き換える。
public function index(Request $request)
{
$data=[
'msg'=>'これはコントローラから渡されたメッセージ',
'id'=>$request->id
];
return view('hello.index',$data);
}
ここであRequestインスタンスを渡している。渡す値は$request->$id
のようにして引き渡している。
Route::get('hello', 'HelloController@index');
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
という名前で作成する。
では記述していく
<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>
ポイントは{{$msg}}
と書いているところ。
Bladeでは{{変数}}
のようにしてテンプレに埋め込む。
アクションの修正
次にコントローラのアクションメソッドを修正していく
public function index()
{
$data=[
'msg'=>'これはコントローラから渡されたメッセージ'
];
return view('hello.index',$data);
}
アクションメソッドは変わらない。
web.phpはこのように。
Route::get('hello', 'HelloController@index');
/helloにアクセスすると正しく表示できている。
index.php
とindex.blade.php
今回アクションメソッドでview('hello.index',...
としているのindex.blade.php
のほうが実行されている。
LaravelではBladeテンプレがあるとそれが優先して読み込まれる。
フォームを利用する
フォームを利用してみる
以下のように修正する。
<body>
<h1>Blade/Index</h1>
<p>{{$msg}}</p>
<form action="/hello" method="post">
@csrf
<input type="text" name="msg">
<input type="submit">
</form>
</body>
ポイントはこれ
@csrf
Bladeディレクティブといい、テンプレに決まったコードを生成して書き出す。
CSRF対策について
@csrfはCSRF対策のためのBladeディレクティブ。
CSRFはスクリプトなどから外部からフォームを送信するもので、フォームに大量のコンテンツを送りつけりする。
@csrfはトークンというランダムな非表示フィールドとして追加する。
このトークン値が正しいフォームだけを受け入れるようにする。
こうすることで正しいフォームからの送信かどうかを見分けることができる。
LaravelではCSRF対策がなされていないフォームの送信は例外が発生して受付けられないようになっている。
そのため、フォームを利用するときは必ず@csrfをフォームに用意しておく必要がある。
アクションの用意
コントローラアクションを用意する。
ここでは2つの処理を書いていく
- /helloへアクセスしたとき
- フォームを送信したとき
以下のように修正する。
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);
}
indexメソッドは/helloにアクセスしたときの処理。
postメソッドはフォームを送信したときの処理
ここでRequestインスタンスを引数に渡してフォームの内容を取得している。
$msg=$request->msg;
フォームのところにname="msg"
と指定したのは
$msg=$request->msg;
で取得するため。
フォームで送信された値はすべてnameプロパティとして取り出せる。
POSTのルート設定
ルート情報を追記する
Route::post('hello', 'HelloController@post');
POST送信はRoute::postを設定する。使い方はROoute::getと同じ。
同じアドレスでもPOST,GETのようにアクセスするメソッドが違えば両方ともに使える。