こんにちは!
PHPのLaravelやJavaScriptでWeb開発をしているフリラーンスエンジニアのファドと申します!
こちらの記事はLaravel教材の第3回目の記事になります。
その他のLaravel教材を学習したい方は下記リンクから直接教材へ飛ぶことができます。
-
Laravel教材
【Laravel教材①】ブログシステムを実装しながらLaravelの基礎を徹底的に学ぶ!〜環境構築編〜
-
Laravel教材
【Laravel教材②】Laravelでブログシステム構築!〜DB接続からテストデータの作成編〜
-
Laravel教材
【Laravel教材④】Laravelでブログシステム構築!〜全記事一覧画面実装から記事詳細画面実装編〜
-
Laravel教材
【Laravel教材⑤】Laravelでブログシステム構築!〜記事投稿機能実装編〜
-
Laravel教材
【Laravel教材⑥】Laravelでブログシステム構築!〜記事編集機能実装編〜
-
Laravel教材
【Laravel教材⑦】Laravelでブログシステム構築!〜記事削除機能実装編〜
MVCモデル
これからの学習をよりわかりやすくするためにMVCモデル
というアプリケーションを作成する際のデザインパターンについて説明していきます。
MVCモデルとはアプリケーション開発で採用されるコードの構成手法です。ユーザーに対する入出力処理とシステムの内部処理を分離すること
を目的としており、システムの機能を3つの役割に分けて開発を行っていきます。
モデル(Model)
1つ目はモデルです。
主にアプリケーションのデータに対する操作を担います。
データベースへデータ登録する処理やデータ取得の処理を記述することが理想です。
ビュー(View)
2つ目はビューです。
主にユーザーに対する入出力処理を担います。
実際にユーザーが見る画面がこのViewです。
コントローラー(Controller)
そして最後はコントローラーです。
主にModel
とView
の橋渡しを担います。
ビューを表示させる処理やデータをモデルからビューへ渡す処理など幅広い処理を記述することができます。
3つの関連性
これら3つの頭文字をとりMVCモデル
と呼ばれています。
LaravelではMVCモデル
が採用されており「どのディレクトリにM・V・Cを格納するのか」がざっくり決まっています。
また、LaraveだけではなくRubyのフレームワークであるRuby on Rails
などでも採用されており、その他にもたくさんのフレームワークがMVCモデルを採用しています。
そんな汎用性の高いMVCモデルですが、それぞれ3つの関連性をわかりやすくするために図を使って説明していきます。
上の図を見てください。
MVCモデルの場合、クライアントからアクセスが来るとアクセスの処理をController
へ割り振ります。
データの取得や変更などを行う場合は、Controller
からModel
に移動してデータの処理を行います。Model
ではデータベースとの接続ができるので、受け取ったデータを処理した後にController
へデータを渡します。
その後Controller
からView
へデータを受け渡し、View
でサイトの表示を行うという流れになっています。
流れを確認しただけですべてを理解することはできないので、それぞれのModel
、View
、Controller
について学習しながら、少しずつ理解していきましょう!
今の段階では、「Laravelはサイトを表示するための役割を3つに分けて実装していくのだな」というイメージを持っておいていただければOKです。
★検索ワード
・フレームワーク MVCとは
・Laravel MVC
モデルについて
それではさっそくMVCの中のモデル(Model)
について学習していきます。
先ほども説明した通り、モデルはデータベースへのアクセスやデータ操作などの役割を担います。
Laravelでは、モデルを簡単に実装するための仕組みが用意されているのでさっそく使ってみましょう。
モデルファイルの作成
モデルファイルもマイグレーションファイルやシーダーファイルのように、Artisanコマンド
を使用して作成することができます。
※Artisanコマンド
とは、php artisan ~~~~~~
のコマンドのことです。
コマンドは以下の通りです。
$ ./vendor/bin/sail php artisan make:model クラス名
基本クラス名はモデルを使用して操作したいテーブル名の単数形を使用します。
そのため、articlesテーブル
のデータを取得したりするモデルファイルを作成する場合のモデル名はArticle
となります。
それではarticlesテーブル
のモデルファイルを作成するので、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:model Article
Model created successfully.
と出力されればモデルファイルの作成は完了です。first-app/app/Models
配下にArticle.php
が作成されていればOKです。
Laravelのモデルは、Eloquentモデル
とも言うことができます。Eloquent
とはLaravelで提供されているデータ操作のための機能であり、モデルとデータベースを紐付ける役割をしています。
それでは作成したArticle.php
を確認してみましょう。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
}
ファイルの中にはModelクラス
を継承したArticleクラス
が作成されています。Modelクラス
はLaravelが初期機能として持っているクラスであり、このクラスを継承しているため、Articleクラス
はモデルとしての機能を発揮することができます。
また、作成したArticleクラス
とLaravelに接続しているデータベースのarticlesテーブル
が、Laravelによって自動的に紐づけられます。
よって、Articleクラス
を操作することで簡単にテーブルの操作を行うことができます。
Article.php
の中のArticleクラス
と、データベースのarticlesテーブル
で名前が単数形と複数形で異なることに注意してください。
Eloquentでは、モデルのクラス名を複数形にしてアッパーキャメルケースだったものをスネークケースにしたものが、紐づけ先のテーブルとして自動的に認識されます。
少し難しい言葉が並んでいますが、例は下記の通りです。
※アッパーキャメルケース例:OpenHours
のように先頭の文字と単語の区切り文字を大文字している名前
※スネークケース例:open_hours
のようにアンダースコア(アンダーバー)で区切られている名前
例えば「admin_statuses」というテーブルに紐づけたい場合のクラス名は、下記のようになります。
①単数形にする(admin_statuses->admin_status)
②アッパーキャメルケースにする(admin_status->AdminStatus)
つまり、php artisan make:model AdminStatus
というコマンドになります。
今回は、articlesテーブル
に紐づけたいので、Article
というファイル名にしてあります。
※モデルのクラス名に拡張子が付いたものがモデルのファイル名になります。
モデルの記述
モデルファイルはほとんど中身を変更せずに使用することができますが、追加しておいた方がいいこともあります。
まずは、下記の通りfirst-app/app/Models/Article.php
を編集してください。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
// テーブル名
protected $table = 'articles';
// 可変項目
protected $fillable = [
'title',
'content',
];
}
まず追加したのは下記のコードです。protected $table = 'articles';
先ほど説明した通り、モデルファイルはテーブル名の単数形であり、アッパーキャメルケースであれば、自動的にテーブルとモデルが紐付けられますが、protected $table
を使用することで任意のテーブル名を指定することもできます。
もしモデルクラス名とテーブル名が全く違う場合などはこのように記述してください。
今回のコードであれば、記述しなくても自動的にモデルファイルとテーブルは結びついていますが、解説のためにこちらも記述しております。
次に追加したのが下記のコードです。
// 可変項目
protected $fillable = [
'title',
'content',
];
こちらのコードはコントローラーなどでデータベースに登録する際に使用するcreateメソッド
を使うために記述します。createメソッド
を使用しない場合は必要ありませんが、将来的に使用するので初めに記述しておきましょう。
まずはprotected $fillable = []
と記述し、[]
の中にはテーブルの可変項目のカラム名を記述していきます。
今回はarticles
テーブルの2つのカラムtitle
とcontent
は、各レコードによって入れたい値が可変になるので[]
に記述しています。
基本$fillable
にはidカラム
とcreated_atカラム
、updated_atカラム
以外のカラムを入れておけばOKです。
状況に応じてidカラム
やcreated_atカラム
、updated_atカラム
なども入れておきましょう。
これでモデルファイルの作成は終わりです。
モデルを学習しただけだと全体像が掴めないと思うので、次に進んでみましょう。
★検索ワード
・Laravel モデル作成
・Laravel Eloquent
・Laravel fillable guarded
・Laravel モデル テーブル名指定
ルート(Route)について
LaravelにはMVC
の他にルート(Route)
という機能が存在しています。
今回はそんなルートについて学習していきましょう。
ルートとは
ルートとはLaravelでルーティングを行う機能です。
ルーティングとはブラウザからアクセスがあった際に、どのコントローラーのどの処理を動かすのかを定義することを言います。
もう少しわかりやすく言うと、「あるURLへリクエストがあったとき、コントローラーのどのメソッドを実行するのかを命令する機能」です。
MVCの図にルートを追加してもう一度確認してみましょう。
このようにブラウザからあるURLへアクセスがあると、始めにルートにたどり着き、どのコントローラーのどのメソッドに処理を振り分けるか決定します。
そこから振り分けられたコントローラーが指定されたメソッドを実行するというイメージです。
では、なぜルートという機能が必要なのでしょうか?
それは、コントローラーはアプリケーション内に複数あることが普通であり、URLごとにどのコントローラーのどのメソッドに振り分けるのかを決める必要があるからです。
つまり、ルートがないとURLにアクセスがあった時に、どのコントローラーのどのメソッドを実行すればいいかLaravelが認識できないので、ページを表示することができなくなってしまいます。
このように、ルートはページを表示させるためには無くてはならない機能なのです。
web.phpについて
Laravelではルーティングをfirst-app/routes/web.php
ファイルで行います。web.php
はすでに下記のような記述がされています。
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
※余計なコメントなどは消しています。
Route::get()
というコードが記述されていますが、第一引数に「指定したいパス」、第二引数には「第一引数のパスへアクセスがあった場合に実行する処理」を記述します。
この場合、パスは/
だけなのでhttp://localhost
が開かれたら、return view(‘welcome’);
を実行する、という意味になります。
このルーティングこそが最初に見た下記画面を表示しているルートです。
なお通常、第二引数にはコントローラーとメソッド名を記述しますが、デフォルトの記述のように無名関数を使用してweb.php
にそのまま処理を記述することもできます。
return view('welcome')
は、ヘルパーメソッドのView
を使用して、first-app/resources/views/welcome.blade.php
というBladeファイル
を表示するという意味になります。
※ヘルパーメソッドは、Laravelの中に最初から組み込まれている関数のことです。
また、今回始めてBladeファイルというものが出てきました。
詳しくはビューのレクチャーで説明でしますが、このBladeファイルがLaravelで見た目を表示するためのファイルです。
少しwelcome.blade.php
を見てみましょう。
VSCodeでfirst-app/resources/views/welcome.blade.php
を開いてください。
<!-- ここから上は省略 -->
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end.
</div>
</div>
</div>
<!-- ここから下は省略 -->
今回はwelcome.blade.php
のすべてを表示するととても長くなってしまうので、下記画像の赤枠部分のみを抜粋しています。
ファイルの中身を見ると、Documentation
というテキストやLaravel has wonderful...
という文章が記述されているのがわかると思います。
例えばDocumentation
をドキュメント
と変更して、ファイルを保存すると下記画像のようになります。
Bladeファイルについては後ほど学習するので、現時点で気にする必要はありません。
ルートの記述
では、このweb.php
へ新たに1つのルートを追加してみましょう。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ArticleController; // ここを追加
Route::get('/', function () {
return view('welcome');
});
// 投稿一覧を表示
Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles'); // ここを追加
まず、後ほど作成するArticleコントローラー
を使えるように下記の1文を追加しています。use App\Http\Controllers\ArticleController;
※ArticleController
はまだ作成していません。
このuse文
を使用することで、後ほど作成するコントローラーをweb.php
で使用することができるようになります。web.php
で他のコントローラーを使用する場合はuse App\Http\Controllers\コントローラーのクラス名
を記載しましょう。
初めてのルーティングとして、投稿一覧を表示するためのルートを記述したいので、Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');
というコードを追加しました。
ルートファイルでは、Routeファサード
という便利機能を使用することができます。Route::
と記述したあとにHTTPリクエスト
を記述してください。
今回は記事一覧をただ表示するだけなので、HTTPリクエストはget
を指定していますが、他にもpost
などが使用できます。
第一引数では先ほど学んだ通り'/articles'
というパスを設定しています。
そのため、http://localhost/articles
というURLにアクセスすると、ここへルーティングされるということです。
第二引数内に記述しているArticleCotroller::class
は、後ほど作成するArticleコントローラー
を指定しています。
また、showArticles
はArticleコントローラー
内に定義されているメソッド名です。
つまり[ArticleController::class, 'showArticles']
と記述することで、http://localhost/articles
へアクセスがあった場合にArticleコントローラー
のshowArticlesメソッド
が実行されるということです。
また、Laravelのヘルパーメソッドであるnameメソッド
を使用することによって、ルートごとに名前を付けることができます。
今回の場合だと、記事一覧を表示させる画面のルートにshowArticles
と名前を付けたことになります。
この段階では何が便利かわかりにくいですが、ルートに名前を指定しておけばルートを指定する時にとても便利なので、なるべくわかりやす名前を付けておきましょう!
まとめると、Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');
と記述することで、http://localhost/articles
にアクセスがあった場合、Articleコントローラー
のshowArticlesメソッド
が実行されるということです。
今のArticleコントローラー
を作成する前の状態でhttp://localhost/articlesにアクセスしても、下記画像のようなエラーが発生します。
ArticleCotroller
がないよ!としっかりエラーが出ていますね!
Laravelはエラー画面がとてもわかりやすいのも特徴です!
★検索ワード
・Laravel ルーティング
・Laravel ルート 記述方法
コントローラー(Controller)について
ルートの説明でArticleコントローラー
が登場したので、次はMVCのCであるコントローラー
について説明します。
コントローラーでは、ビューを表示させる処理やモデルからビューへデータを渡す処理など幅広い処理を記述することができます。
Laravelでは、コントローラーを簡単に実装するための仕組みが用意されているのでさっそく使ってみましょう。
コントローラーファイルの作成
コントローラーファイルもArtisanコマンド
を使用して作成することができます。
コマンドは以下の通りです。
$ ./vendor/bin/sail php artisan make:controller クラス名
基本クラス名はテーブル名の単数形にController
を連結させたものです。
そのため、articlesテーブル
のコントローラーを作成する場合のクラス名はArticleController
となります。
それではコントローラーファイルを作成するので、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ ./vendor/bin/sail php artisan make:controller ArticleController
Controller created successfully.
と出力されればコントローラーファイルの作成は完了です。first-app/app/Http/Controllers
配下にArticleController.php
が作成されていればOKです。
それでは作成したArticleController.php
を確認してみましょう。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
//
}
ファイルの中にはControllerクラス
を継承したArticleControllerクラス
が作成されています。Controllerクラス
はLaravelが初期機能として持っているクラスであり、このクラスを継承しているため、ArticleControllerクラス
はコントローラーとしての機能を発揮することができます。
もう一度web.php
に追加したコードを確認してみましょう。
Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');
上記のコードをweb.php
へ追加しましたが、簡単に言うとhttp://localhost/articlesへアクセスがあった場合、Articleコントローラー
のshowArticles
メソッドを実行するという意味でした。
コントローラーの記述
ここまででArticleコントローラー
は作成できたので、showArticlesメソッド
を作成していきましょう。first-app/app/Http/Controllers/ArticleController.php
を下記のように編集してください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
// --- ここから追加 ---
/**
* 記事一覧を表示する
*/
public function showArticles()
{
return view('articles.index');
}
// --- ここまで追加 ---
}
まず、ルーティングで指定したshowArticlesメソッド
を作成します。web.php
で指定したメソッドをコントローラーファイル内で定義する場合は、public function メソッド名(){}
と記述してください。
そして{}
内にメソッドの処理を記述していきます。
今回はreturn view('articles.index')
がshowArticlesメソッド
の処理として記述されています。
このreturn view()
は以前ルーティングのところでも説明しましたが、ヘルパーメソッドのViewメソッド
を使用して、first-app/resources/views
配下のBladeファイルを表示するという意味です。
また、()
内に'articles.index'
と記述されているので、first-app/resources/views/articles/
配下のindex.blade.php
というBladeファイルを表示するという処理になっています。
さらに下記のコメントのようなものが、メソッドの上に追加されています。
/**
* 記事一覧を表示する
*/
これはPHPDoc
と呼ばれていて、クラスやメソッドの上に記述することでどのようなクラスやメソッドなのかを説明することができる機能です。
現段階でPHPDocについて意識する必要は全くないので、コメント程度に思っておいていただければOKです!
ビューを表示する
コントローラーの作成から記述までが終わったので、さっそくhttp://localhost/articlesへアクセスしてみましょう。
アクセスすると下記のようなエラーが出ると思います。
エラーの内容はfirst-app/resources/views/articles
配下にindex.blade.php
というファイルが存在しないという内容です。
showArticlesメソッド
でreturn view('articles.index')
と指定しましたが、まだBladeファイルを作成していないので当然のエラーですね。
では、さっそくBladeファイルを作成してみましょう。
コマンドでも画面上でそのまま作成してもどちらでも大丈夫です。
まずはfirst-app/resources/views
配下にarticles
ディレクトリを作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ mkdir resources/views/articles
次に作成したarticles
ディレクトリにindex.blade.php
を作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ touch resources/views/articles/index.blade.php
作成したindex.blade.php
を開いて、下記の通り編集してください。
Laravelで初めての画面出力
編集して保存したらhttp://localhost/articlesへアクセスしてください。
ブラウザにLaravelで初めての画面出力
と表示されていればOKです。
詳しいBladeファイルの記述方法はビューの解説で説明しますので、まずはコントローラーでBladeファイルを表示する順序だけわかっていただければOKです。
画面表示の流れの確認
一度Bladeファイルを表示する流れをおさらいしておきましょう。
まず、URL(http://localhost/articles
)にアクセスがされると、ルーティングの処理(Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');
)が実行されます。
ルーティングでは、Articleコントローラー
のshowArticlesメソッド
を実行するように処理が記述されています。
そのため、first-app/app/Http/Controllers/ArticleController.php
の中のArticleControllerクラス
のshowArticlesメソッド
を実行します。
showArticlesメソッド
にはreturn view('articles.index')
と記述されており、first-app/resources/views/articles/index.blade.php
を表示する処理になっています。
index.blade.php
を確認するとLaravelで初めての画面出力
とテキストが記述されているので、URL(http://localhost/articles
)にアクセスがされると、ブラウザにLaravelで初めての画面出力
というテキストが表示されることになります。
今回はテキストのみの表示だけだったので、データベースへの接続がない分モデル
は登場しませんでした。
なので、下記画像の②データ処理
と③DB接続
は行っていません。
後ほど記事一覧を表示させる時に②と③の方法については説明します。
★検索ワード
・Laravel コントローラー作成
・PHPDocとは
ビュー(View)について
コントローラーの説明で作成したfirst-app/resources/views/articles/index.blade.php
ですが、このBladeファイルこそがLaravelのビュー(View)
にあたります。
Bladeテンプレートとは
そもそもBladeファイルはBladeテンプレート
というテンプレートエンジンで作成されたファイルのことです。
テンプレートエンジンとは、テンプレート部分とデータを合成してドキュメントを出力するソフトウェアのことを指します。
いまいちイメージが湧かないかもしれませんが、HTMLとPHPが直接記述できる便利機能
だと思っていただければ大丈夫です。
また、Bladeテンプレートではテンプレートの継承
やデータの受け渡し
を簡単に行うことができるようになっており、Laravelを扱う上で必須の知識となるので、さっそく学習していきましょう。
ちなみにテンプレートエンジンはBladeの他にもSmarty
やTwig
などがありますが、LaravelではBlade
を採用しています。
Bladeテンプレートの使い方
Bladeテンプレートには使用できる構文が存在しており、わかりやすいように主なものを表にまとめておきます。
構文 | 説明 |
---|---|
@extends(‘Bladeファイル’) | ()内のBladeファイルを継承することができる |
@yield(‘セクション名’) | ()内のセクション名が同じ@section~@endsectionまでを読み込むことができる |
@section(‘セクション名’) ~ @endsection | @sectionと@endsectionで囲まれた部分を@yield部分に追加する |
@include(‘Bladeファイル’) | ()内のファイルを読み込むことができる |
これらの構文を使用することでHTMLファイルやPHPファイルをそのまま使用するよりも遥かに管理しやすい状態で見た目(View)を作成することができるようになります。
使い方は見た目を実装しながら、順番に説明していきます。
Bladeの記述
先ほども少し触れた通り、BladeファイルにはHTMLをそのまま記述することができます。
なので、ざっくりとした見た目を最初に作成してしまいましょう。
それでは、以前作成したfirst-app/resources/views/articles/index.blade.php
を下記のように編集してください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ブログ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
<header>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">ブログ</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-item nav-link active" href="#">記事一覧 <span class="sr-only"></span></a>
<a class="nav-item nav-link" href="#">記事投稿</a>
</div>
</div>
</div>
</nav>
</header>
<!-- コンテンツ -->
<div class="container mt-4">
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- フッター -->
<footer class="footer bg-primary fixed-bottom">
<div class="container text-center">
<span class="text-light">©︎Laravel教材</span>
</div>
</footer>
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
編集が終わったら保存してhttp://localhost/articlesへアクセスしてみましょう。
下記画像のように画面が表示されればOKです。
まず、記事一覧に表示されている記事自体はHTMLで直接記述しているものになります。
後ほどデータベースから記事を取得して表示させますが、まずはHTMLで直接記述することで記事の表示をしておきます。
また、今回は見た目部分を整えるためにBootstrap
というフレームワークを使用しています。
Bootstrapは複雑なCSSやJavaScriptを記述しなくてもHTMLにclass
やid
を指定することで、簡単に見た目を整えることができるので重宝されています。
そんな便利なBootstrapですが、CDNでお手軽に使用することができます。
Bootstrapを使用する際のCDNは下記のようになっています。
<!-- CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
本教材はLaravelを学習するための教材なのでBootstrapについての解説は省きますが、興味のある方は公式ドキュメントがあるので見てみてください。
※Bootstrapの基本的な使い方は、ドキュメントに記述しているコードをコピペして使用していきます。
Bladeの共通化
それでは、index.blade.php
に全て記述していた見た目部分をBladeの力を使用してヘッダーやコンテンツ、フッターと共通化させていきます。
共通化の流れは下記の通りです。
- 共通のテンプレートである
layout.blade.php
を作成する - 共通のヘッダーを作成する
- 共通のフッターを作成する
index.blade.php
に共通のテンプレートであるlayout.blade.php
を継承させる
共通化
や継承
と言われてもなかなかイメージがしにくいと思うので、まずは実装していきましょう。
layout.blade.phpの作成
それでは共通のテンプレートにするためのlayout.blade.php
を作成しましょう。first-app/resources/views
ディレクトリにlayout.blade.php
をコマンドかVSCode上で作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ touch resources/views/layout.blade.php
作成したlayout.blade.php
にindex.blade.php
の内容をそのまま貼り付けてください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ブログ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
<header>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">ブログ</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-item nav-link active" href="#">記事一覧 <span class="sr-only"></span></a>
<a class="nav-item nav-link" href="#">記事投稿</a>
</div>
</div>
</div>
</nav>
</header>
<!-- コンテンツ -->
<div class="container mt-4">
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- フッター -->
<footer class="footer bg-primary fixed-bottom">
<div class="container text-center">
<span class="text-light">©︎Laravel教材</span>
</div>
</footer>
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
これで今回作成したfirst-app/resources/views/layout.blade.php
とfirst-app/resources/views/articles/index.blade.php
のコードは全く同じ状態です。
共通ヘッダーの作成
次にどのページにも共通するヘッダーであるheader.blade.php
の作成を行っていきます。first-app/resources/views
ディレクトリにheader.blade.php
をコマンドかVSCode上で作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ touch resources/views/header.blade.php
作成したheader.blade.php
にlayout.blade.php
のヘッダー部分をコピーして、下記の通り貼り付けてください。
<header>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">ブログ</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-item nav-link active" href="#">記事一覧 <span class="sr-only"></span></a>
<a class="nav-item nav-link" href="#">記事投稿</a>
</div>
</div>
</div>
</nav>
</header>
また、layout.blade.php
のヘッダー部分を下記の通り編集してください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ブログ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
@include('header')
<!-- コンテンツ -->
<div class="container mt-4">
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- フッター -->
<footer class="footer bg-primary fixed-bottom">
<div class="container text-center">
<span class="text-light">©︎Laravel教材</span>
</div>
</footer>
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
このように@include('header')
と記述することでfirst-app/resources/views/header.blade.php
を読み込むことができます。
つまり、本来であればヘッダー部分をlayout.blade.php
に直接記述していましたが、ヘッダー部分だけをheader.blade.php
で管理することによって、ヘッダーを編集したい場合はheader.blade.php
のみを編集すればいいことになります。
このようにヘッダー部分を別ファイルで管理することによってメンテナンス性の向上
や可読性
に繋がります。
共通フッターの作成
それではヘッダーと同じように、どのページにも共通するフッターfooter.blade.php
の作成を行っていきます。first-app/resources/views
ディレクトリにfooter.blade.php
をコマンドかVSCode上で作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-app
ディレクトリ上で実行してください。
$ touch resources/views/footer.blade.php
作成したfooter.blade.php
にlayout.blade.php
のフッター部分をコピーして、下記の通り貼り付けてください。
<footer class="footer bg-primary fixed-bottom">
<div class="container text-center">
<span class="text-light">©︎Laravel教材</span>
</div>
</footer>
また、layout.blade.php
もフッター部分を下記の通り編集してください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ブログ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
@include('header')
<!-- コンテンツ -->
<div class="container mt-4">
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- フッター -->
@include('footer')
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
ヘッダーと同じく@include('footer')
と記述することでfirst-app/resources/views/footer.blade.php
を読み込むことができます。
これでフッター部分はfooter.blade.php
で管理することができるようになりました。
index.blade.phpにlayout.blade.phpを継承させる
それでは、残っているコンテンツ部分を@yield
と@section~@endsection
で読み込ませるようにしてから、index.blade.php
にlayout.blade.php
を継承させていきます。
コンテンツの表示
まずはコンテンツ部分を@yield
と@section~@endsection
を使用して読み込ませる記述をしていきます。
layout.blade.php
を下記の通り編集してください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ブログ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
@include('header')
<!-- コンテンツ -->
<div class="container mt-4">
@yield('content')
</div>
<!-- フッター -->
@include('footer')
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
まず共通のレイアウトとなるlayout.blade.php
のコンテンツ部分にある<div class="container mt-4"></div>
以外のコードを全て削除してから、代わりに@yield('content')
と記述します。
このように@yield('content')
と記述することで、あるファイルでlayout.blade.php
が継承された時に@section('content')
と@endsection
で囲まれた部分を@yield('content')
部分に読み込ませることができます。
それではindex.blade.php
でlayout.blade.php
を継承して、@section('content')
と@endsection
で囲んだ部分にコンテンツを記述してみましょう。
index.blade.php
を下記の通り編集してください。
@extends('layout')
@section('content')
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
@endsection
まず継承するためには@extends()
を使用します。@extends()
を使用し()
内に継承したいBladeファイルを記述することで、index.blade.php
に()内で指定したBladeファイルを継承することができます。
今回はindex.blade.php
にlayout.blade.php
を継承したいので、@extends('layout')
となります。
無事にlayout.blade.php
を継承することができたので、layout.blade.php
の中に記述されている全てのコードがindex.blade.php
に記述されているのと同じ状況を作り出すことができました。
そして、最後にindex.balde.php
の先ほどlayout.blade.php
で削除したコンテンツ部分を@section('content')
と@endsection
で囲まれた部分に記述すればOKです。
さっそくhttp://localhost/articlesへアクセスしてみましょう。
下記画像のように画面が表示されればOKです。
これで無事にコンテンツ部分を読み込ませることに成功しましたが、実はあと1つ@yield()
と@section()~@endsection
で記述した方が良い箇所があります。
それはlayout.blade.php
のtitle要素
です。
タイトル部分はページ毎に変更したいので、ここも@yield()
を使用してページ毎に変更可能にさせましょう。
それでは、layout.blade.php
を下記の通り編集してください。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>@yield('title', 'ブログ')</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
</head>
<body>
<!-- ヘッダー -->
@include('header')
<!-- コンテンツ -->
<div class="container mt-4">
@yield('content')
</div>
<!-- フッター -->
@include('footer')
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/js/bootstrap.min.js" integrity="sha384-oesi62hOLfzrys4LxRF63OJCXdXDipiYWBnvTl9Y9/TRlw5xlKIEHpNyvvDShgf/" crossorigin="anonymous"></script>
</body>
</html>
変更した箇所は、title要素
の中身です。
変更前はブログ
というテキストのみを記述していましたが、このままだと全てのページでtitle要素
がブログになってしまいます。
代わりに@yield('title', 'ブログ')
と記述することで、layout.blade.php
を継承したファイルで@section('title')~@endsection
を使用することで、ページ固有のタイトルを決めることができるようになります。
また、万が一継承したファイルに@section('title')~@endsection
がない場合も@yield()
の第二引数であるブログ
がページのタイトルになるので、設定し忘れたとしてもしっかりとタイトルブログ
が表示されます。
では、次にindex.blade.php
を下記の通り編集してください。
@extends('layout')
@section('title')
記事一覧
@endsection
@section('content')
<div class="row">
<h2>記事一覧</h2>
<table class="table table-bordered table-hover ">
<thead class="bg-info text-light">
<tr>
<th scope="col">#</th>
<th scope="col">タイトル</th>
<th scope="col">内容</th>
<th scope="col">日付</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>テスト1</td>
<td>テスト1です。</td>
<td>2022/01/01</td>
</tr>
<tr>
<td>2</td>
<td>テスト2</td>
<td>テスト2です。</td>
<td>2022/01/02</td>
</tr>
</tbody>
</table>
</div>
@endsection
追加したコードは以下の通りです。
@section('title')
記事一覧
@endsection
layout.blade.php
で@yield('title')
と記述したので、index.blade.php
では@section('title')~@endsection
と記述します。
また、index.blade.php
は記事一覧を表示させるためのページなので、記事一覧
というページタイトルにしています。
それでは改めてhttp://localhost/articlesへアクセスしてみましょう。
下記画像のように画面が表示されていて、Chromeのタブ部分であるページタイトルが記事一覧
になっていればOKです。
このようにBladeで共通化してもユーザーが見る見た目はindex.blade.php
へ全てのHTMLを記述したときとまったく変わっていません。
その代わりindex.blade.php
の内容はlayout.blade.php
を継承したことで大きく変わっています。
これからBladeファイルを作成するときはlayout.blade.php
を継承し、title
とcontent
部分だけを記述すればページが完成します。
まだ記事一覧ページしか作成していないのでBladeの恩恵を感じにくいかもしれませんが、これから記事詳細画面や記事作成画面、記事編集画面を作成していく中でより恩恵を感じられると思います。
ひとまず記事一覧画面の見た目の作成はこれで完了です。
★検索ワード
・Laravel view 作成
・Laravel view 共通化
・Laravel @extends
・Laravel @yield
・Laravel @section @endsection
・Laravel @include
・Bootstrap 使い方
次の教材
次の教材は下記から簡単に飛ぶことができます!
引き続きプログラミングを楽しんでいきましょう!
プログラミング学習サポートについて
「独学で挫折した。。。」
「一人でのプログラミング学習がしんどい。。。」
「未経験からエンジニア転職をしたいけど何をしたら良いかわからない。。。」
このような悩みをお持ちの方向けに、本教材作成者のファドがMENTAという学習サイトにてあなたのプログラミング学習とエンジニア転職を徹底サポートいたします!
サポート価格はなんと1日あたりたったの約300円!
教材で分からない箇所のサポートはもちろんのこと、本サイトで公開しているすべての課題の解答も公開しております。
また、MENTAで学習を終わらせていただいた方限定で懇意にしていただいている企業さんを紹介することもあります!
なお、サポート内容の詳細は下記の通りです。
- 目標設定
- マインドセット
- オリジナル教材見放題
- オリジナル課題見放題
- オリジナル課題の解答見放題
- 課題コードレビュー
- 教材への無制限質問
- 課題への無制限質問
- ポートフォリオ作成アドバイス
- 褒めのコーチング
いくつかのプランを用意させていただいておりますので、下記より一度ご覧ください!
コメント