2. 会社概要ページの作成 #Laravelの教科書 #Laravelを使ったウェブサイトの開発
こちらの記事はLaravelを使ったウェブサイトの開発の2回目です。
表紙はこちらです。
# 課題
本稿の課題は以下です
・会社概要ページを表示するためのAboutPageControllerクラスを作成する
・ルーティング設定ファイルを変更し「/about」で会社概要ページを表示出来るようにする
・ナビゲーションを変更して会社概要ページへのリンクを貼る
・ControllerからViewに値を渡せるようになる
課題の成果物のイメージ
# 会社概要ページのテンプレートを用意する
会社概要ページ用のテンプレートファイルを作成します。
テンプレートファイルの設置先はトップページと同じ「resources/views」です。こ
ちらのパスに「about.blade.php」ファイルを作成します。パス全体は次のようになります。
resources/views/about.blade.php
会社概要ページは次のようにトップページに近い形で作成しました。
about.blade.php
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{{ asset('css/style.css') }}" />
</head>
<body>
@include("parts.header")
<main>
<h1>会社概要ページ</h1>
</main>
@include("parts.footer")
</body>
</html>
# AboutPageControllerクラスの作成
続いて会社概要ページを表示するためのControllerを作成します。
AboutPageControllerクラスの設置場所はTopPageControllerと同じ「app/Http/Controllers」以下です。
パス全体は次のようになります。
app/Http/Controllers/AboutPageController.php
AboutPageController.php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class AboutPageController extends Controller{
public function show(){
return view('about');
}
}
AboutPageControllerクラスには会社概要テンプレートを表示するためのshow()を追加します。
# ルーティングの変更
ルーティング設定ファイル「routes/web.php」を編集し、/aboutにアクセスしたらAboutPageControllerのshow()が起動するように設定します。
routes/web.php
//トップページ
Route::get('/', 'TopPageController@show');
//会社概要ページ
Route::get('/about', 'AboutPageController@show');
この時、/aboutの末尾の「/」は不要です。
この設定で「/about」「/about/」どちらでアクセスしてもAboutPageControllerクラスのshow()メソッドが呼び出されます。
ファイルを保存したらブラウザより「http://localhost:8000/about/」を開いて会社概要ページが表示されることを確認してください。
表示されない場合は次のことを確認してください
・サーバーは起動していますか?前項(https://note.com/laravelstudy/n/n98f754efc6da)を参考にサーバーの起動を行ってください
・会社概要ページのテンプレート名とAboutPageControllerクラスの設定は正しいでしょうか?
# ナビゲーションの設定
ナビゲーションはトップページにしかリンクが設定されていないので、ここに会社概要ページのリンクを追加します。
CSSの読み込みにはasset()関数を使いましたが、Laravelのルーティング先にリンクを設定する場合は「url()」関数を使います。
ナビゲーションを次のように変更してください。
views/parts/nav.blade.php
<nav>
<a href="{{ url('/') }}">トップ</a>
<a href="{{ url('/about') }}">会社概要</a>
</nav>
{{ url('ルーティング設定ファイルで指定したURL') }}と書くことでLaravelのルーティング先へのURLが正しく表示されます。
現在は/aboutに設定しているので{{ url('/about') }}と書いています。
ファイル保存後、ブラウザで「http://localhost:8000/about/」を開いてトップページ、会社概要を行き来できることを確認してください。リンクが間違っているとエラーページが表示されます。
エラーページ
# タイトルを出力する
会社概要ページを作ったところで<head>〜</head>も各テンプレートで出現するため、部品にしたほうが効率が良さそうなことに気づきました。
そのため、<head>部分を出力するための共通部品【parts.common】を作成します。
views/parts/common.blade.phpを次のように作成してください。
views/parts/common.blade.php
<!DOCTYPE html>
<html>
<head>
<title>株式会社○○</title>
<link rel="stylesheet" href="{{ asset('css/style.css') }}" />
</head>
<body>
読み込み側は次のように書き換えます。
views/parts/top.blade.php
@include("parts.common")
@include("parts.header")
<main>
<h1>これはトップページです</h1>
</main>
@include("parts.footer")
</body>
</html>
views/parts/about.blade.php
@include("parts.common")
@include("parts.header")
<main>
<h1>会社概要ページ</h1>
</main>
@include("parts.footer")
</body>
</html>
各ページの共通部品が整理されてスッキリしましたね。
ブラウザでトップページを開いてタイトル部分に「株式会社○○」と表示されているか確認してください。
# タイトルをページ毎に書き換える
タイトルは出るようになりましたが、今のままでは会社概要ページとトップページの区別がつきません。
トップページでは「株式会社○○」と表示して、会社概要ページでは「会社概要 - 株式会社○○」と表示したい場合どうするのが良いでしょうか。
解決方法はいくつかあるので、順に作ってみます。
# common.blade.phpで条件をわけて対応する
URLが「/about」の時は「会社概要 - 株式会社○○」と表示するというテンプレートを作成します。
このような条件を指定するためにphpのif文と同じ構文がbladeテンプレートにも用意されています。条件の設定は「@if〜@elseif〜@else〜@endif」構文を使います。
common.blade.phpを次のように書き換えてください。
views/parts/common.blade.php
<!DOCTYPE html>
<head>
@if(Request::is('about'))
<title>会社概要 - 株式会社○○</title>
@else
<title>株式会社○○</title>
@endif
<link rel="stylesheet" href="{{ asset('css/style.css') }}" />
</head>
書き方はPHPとほぼ同じです。
@if(条件式)
条件式=trueの時実行
@elseif(条件式2)
条件式2=trueの時実行
@else
それ以外の時実行
@endif
Request::is('about')で「/about」にアクセスした時の条件を設定することが出来ます。Request::is()関数の時は先頭の「/」が無いことに注意してください。
ブラウザでトップページと会社概要ページを開いてみてタイトルが書き換わっていることを確認してみてください。
この書き方はシンプルですが、下層ページが増える度に書き換えが発生するのであまり効率的ではありません。
# 呼び出し元のテンプレートからタイトルを渡す
@include構文は引数に指定することで、別のテンプレートに値を引き継ぐ事ができます。
こちらを利用し、呼び出し元のテンプレートからタイトルを渡す形にします。
about.blade.phpを次のように書き換えてください
views/parts/about.blade.php
@include("parts.common")
↓
@include("parts.common", [ "title" => "会社概要" ])
こちらは【parts.common】テンプレートに【変数titleを指定して呼び出す】という意味です。
呼び出し元から渡された変数は「{{ $変数名 }}」で表示することが出来ます。
views/parts/common.blade.php
<!DOCTYPE html>
<head>
<title>{{ $title }} - 株式会社○○</title>
<link rel="stylesheet" href="{{ asset('css/style.css') }}" />
</head>
common.blade.phpテンプレートは少しシンプルになりました。
「http://localhost:8000/about/」を開いてタイトルが出ていることを確認してください。
しかしながら、この状態でトップページ(http://localhost:8000/)を開くと「Undefined variable: title 」というエラーが表示されます。
トップページでも同じparts.commonを利用していますが、そこではtitleを指定していなかったことが原因です。
この書き方の問題点はこのように呼び出し元を全て書き換える必要があり、もし指定していなかったらエラーになってしまうことです。
それを避けるために、@isset構文を使います。書き方は@if〜@elseif〜@else〜@endifと似た構文です。
@isset($変数名)
あるとき
@else
ないとき
@endif
完成形となるparts.commonテンプレートは以下のようになります。
views/parts/common.blade.php
<!DOCTYPE html>
<head>
@isset($title)
<title>{{ $title }} - 株式会社○○</title>
@else
<title>株式会社○○</title>
@endisset
<link rel="stylesheet" href="{{ asset('css/style.css') }}" />
</head>
@isset〜@else〜@endissetでタイトルの出し分けを行っています。
ブラウザでトップページ、会社概要ページと行き来して問題がないことを確認してください。
# Controllerから値を渡す
テンプレートからテンプレートに値を引き継ぐことは出来るようになりました。
LaravelではControllerからテンプレートに値を渡すことも出来ます。Controllerからテンプレートに値を渡す場合、view()関数の引数に引数を設定します。
AboutPageControllerを次のように変更して現在の時間を渡して見ましょう。
app/Http/Controllers/AboutPageController.php
...(略)
class AboutPageController extends Controller{
public function show(){
return view('about', [
"current_time" => date("Y-m-d H:i:s")
]);
}
}
受け取った値をテンプレートで表示します。表示は同じように{{ $変数名 }}で記載します。
views/parts/about.blade.php
@include("parts.common", [ "title" => "会社概要" ])
@include("parts.header")
<main>
<h1>会社概要ページ</h1>
<p>現在の時間は {{ $current_time }} です<p>
</main>
@include("parts.footer")
</body>
</html>
「http://localhost:8000/about/」を開いて表示が次のようになっていること、リロードの度に時間がどんどん変わっていくことを確認してください。
# まとめ
本稿を振り返り、次のことを確認してください
・新しいページを追加する流れ(テンプレートの作成、Controllerの作成、ルーティングの設定)
・テンプレートでリンクを貼るときはurl()関数を使う
・@if構文を使った条件指定
・値をテンプレート→テンプレートに渡す方法
・値をController→テンプレートに渡す方法
ここまでの内容をGitHubで公開しています。
https://github.com/laravelstudy-note/company_site/releases/tag/v0.1.2
次回は存在しないページにアクセスした時のエラー画面をカスタマイズします。
おつかれさまでした!
---
Laravelの教科書
表紙はこちらです
完成まで突っ走る意気込みです。サポートしていただけると非常に嬉しいです。応援よろしくお願いします。