こんにちは!前回はログイン機能を実装しましたね!
ここから本格的にlaravelのプログラミングパートです!張り切っていきましょう!🔥🕺🔥 < アッツゥゥゥ!
- チュートリアル説明
- プログラミングの準備(エディタ、dockerの用意、環境構築)
- 認証機能を追加してログイン機能を実装する
- ブログのタイトルと記事を登録する(今ここ)
- ブログの記事へタグを登録する
- ブログの一覧表示、編集機能の実装
- ブログの検索機能の実装
- ユーザーへの通知機能の実装
さぁ、ようやくブログの投稿機能を実装していきます!
laravelはMVCパターンを採用しているので、その仕様に沿って投稿機能を実装していきます。
MVCパターンとは
MVCとはModel・View・Controllerの略です。
複雑になりがちなプログラミングの処理を3つの役割に分割して実装する手法です。
各モジュールが比較的はっきりと分かれるのでプログラムの見通しがよくなります。
また、ユーザインタフェース (UI) 部分を別のモジュールに取り替えることが容易となるのもメリットの1つです。
デザインパターンの1つとして扱われることからMVCパターンと呼んだりします。
参考の記事を読んでいただければなんとなくわかるかと思いますが、一応私のニュアンスというか見解も書いておきます。
- M: モデル(データベース連携、操作。テーブルに保存されているレコードになったり、保存前のレコードになったり、レコードを作成(保存)したり。こんな感じでデータベース周りの処理を簡単にしてくれるもの。model)
- V: ビュー(目に見える部分。ページとかを表示させたり、表示に必要なデータを持って表示させたりしてくれるもの。view)
- C: コントローラ(ビューなどからリクエストを受け取ってレスポンスを返す。記事のタイトルなどをviewから受けとってモデルに渡したり、必要なパラメータをviewに渡したり。アプリケーションに必要な処理をメイン?でやるところ。controller)
こんな感じです!(本当ざっくりしててすいません。)
まぁやっていけばなんとなくわかると思いますので、今はふーんて思っててもらって大丈夫です!
ということで、早速やっていきましょう!
routeの設定
まず、routes/web.phpを見てみましょう
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
はい、こんな感じですね
これはルート(route)と言われるものです
laravelのwelcomeページを表示した時を思い出してみてください。
http://localhost:8080/public
とブラウザに入力しましたよね?
publicが少しわかりづらくなる要因かもしれませんが、laravelはpublicディレクトリのindex.phpを最初に読み込まないと処理を開始できません。
で、上記のパスを打ち込むと、publicディレクトリの中からindex.phpのファイルを探して実行します。
(この動きは環境構築でインストールしたapacheというwebサーバーソフトウェアの挙動らしいです。nginxだと多分index.phpを指定しないと探してくれなそうです。よくわからなくても大丈夫です。あと、設定すればpublicを省略することもできたはずです。)
試しに
http://localhost:8080/public/index.php
と入力してみてください。
おそらくwelcomeページが表示されると思います。
さらに、このブログサイトの
https://begien.com/
の後ろに「index.php」を入力してみてください。
おそらくホーム画面が表示されているはずです。
つまり、このブログサイトは、内部的に
https://begien.com/ === https://(アプリケーションの名前)/public
こんな感じになっているということです。
なので、urlにpublicを含めないと処理を開始できないのでpublicを入力しているわけです。
で、なんでwelcomeページが表示されるかと言うとweb.phpに
Route::get('/', function () {
return view('welcome');
});
こんな記述がありますよね。これを紐解くと、
get
httpリクエストのgetメソッドで(ブラウザに入力するurlとか)、
'/'
ルートディレクトリにアクセスしたら(http://localhost:8080/public/)
function () {
funciton内に書かれた処理を実行します。
return view('welcome');
viewのwelcomeページを返します(表示します)。
(この'view'がMVCでいうところのVです!さぁMVCパターンが出てきました!)
試しに以下の内容をweb.phpに貼り付けてください。
Route::get('/test', function () {
return 'test';
});
で、ブラウザに
http://localhost:8080/public/test
と打ち込んでみてください。
'test'とブラウザに表示されましたか?
これがルートの基本です!
なんとなくルートがわかったと思うので、記事の投稿ページを作成していこうと思います!!
では、welcomeページに記事を投稿する画面へのリンクを貼りましょう!
resources/views/welcome.blade.phpを開いてください。
~~省略
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ route('login') }}">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}">Register</a>
@endif
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel
</div>
<div class="links">
<a href="https://laravel.com/docs">Docs</a>
<a href="https://laracasts.com">Laracasts</a>
<a href="https://laravel-news.com">News</a>
<a href="https://blog.laravel.com">Blog</a>
<a href="https://nova.laravel.com">Nova</a>
<a href="https://forge.laravel.com">Forge</a>
<a href="https://vapor.laravel.com">Vapor</a>
<a href="https://github.com/laravel/laravel">GitHub</a>
↓追記
<a href="#">記事投稿</a>
</div>
</div>
</div>
</body>
まだルートを設定していないので、リンク先は'#'としておきます。
(この<div>とか<a>とかはhtmlというプログラム言語?マークアップ言語?で、ブラウザに何かを表示するための骨組みみたいなものを作成するために必要な言語です。今回はhtmlについては特に詳しく説明しません。気になった方はご自身で調べてみてください🙇♂️)
で、welcomeページをリロードしてみてください。
はい、「記事投稿」が表示されてますね!
では、ここをクリックしたら記事の投稿ページに遷移するようにルートを定義します!
web.phpを開いて下さい。
で、先ほどのtestのルートを削除してもらって、
Route::get('/article/new', 'ArticleController@new')->name('article.new');
これを貼り付けてください。
先ほどと違う書き方ですね!
これは、
get
のhttpメソッドで、
/article/new
というurl(http://localhost:8080/public/article/new)にアクセスしたら
ArticleController
というコントローラ(ファイル)の
new
アクションを実行します。
->name('article.new');
このルートの名前は、article.newです
ということになります。
さぁ、Controllerという文字が出てきましたね!MVCのCです!
ということで、ArticleControllerを作成しましょう!
controllerの作成
ターミナルを開いてください。
で、appコンテナに入ってください。
で、その中で、
php artisan make:controller ArticleController
と入力してエンターを押してみてください。
はい、Controllerの作成に成功したみたいです。
ではapp/Http/Controllers/ディレクトリの中を見てみましょう
はい、ArticleController.phpというファイルが出来上がってますね!
では、中身を見てみましょう!
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
//
}
はい、こんな感じですね。
//
ここに処理を書いてくださいと言わんばかりのコメントアウトがされてます。laravel親切ですね!
ということで、先ほどルートで定義したnewアクションを定義します!
class ArticleController extends Controller
{
public function new ()
{
return view('article.new');
}
}
先程のコメントアウトを消して上記のようにnewアクションを定義してください。
で、試しにブラウザに
http://localhost:8080/public/article/new
と打ち込んでみましょう。
はい、エラー画面が出ましたね。いい感じです!
View[article.new] not found.
つまり、
return view('article.new');
これで返している(表示する)viewが見つかりません。ということです。
(少し脱線しますが、最初はエラー画面に抵抗を感じる方が多いと思いますが、プログラミングはエラーとの戦いでもあって、エラー解消のため時間の大半を使うことも珍しくありません。よくよくエラー内容を確認すると「あーそんなことか」と簡単に解消することもあります(しないときもあります)。エラーは友達と思って、今のうちに慣れておきましょう!
それでもエラー画面を見るとフラストレーションを感じる方は、エラー画面に向かってパンチしましょう!そしてパソコンが壊れたらまた買ってください!)
と言うことで、article.newのviewを作ればエラーは解消されるはずなので、article.newのviewを作成しましょう!
viewの作成
以下のようにresources/views/にarticle/new.blade.phpを作成しましょう。(コマンドはありません。純粋にarticleディレクトリを作成して、new.blade.phpというファイルを作成してください。)
で、作成したファイルの中身に
hello world!!
とだけ書いて、保存してください。
で、もう一度
http://localhost:8080/public/article/new
にアクセスしてみてください。
hello world!!が表示されましたか?されていればOKです!
ここで少し、今の処理の流れをMVCで説明します。
client(あなた)が、ブラウザにarticle/newページを表示してくださいとurl(http://localhost:8080/public/article/new)を打ち込んでrequest(リクエスト)する
↓
controller(コントローラ)がrequestを受け取り、指定されたresponse(レスポンス)のview(ビュー)を返す(表示する)
という感じです!
MVCのVCを使ったということですね!
Mはもう少し先になります。
はい、そしたら、先ほどwelcomeページに貼ったリンクにurlを指定しましょう。
<a href="{{route('article.new')}}">記事投稿</a>
'#'を消して、上記のように書き換えてください。
この書き方は、blade特有?で、
{{}}
これは、この中に記述したphpのプログラムで出力された内容を表示するための記法になります。
なんとなくわかってればオッケーです
で、
route('article.new')
これは、先ほどrouteに記載した
->name('article.new');
のnameを見て、urlを作って表示してくれる書き方になります。
普通に
http://~~
と書くより簡単ですね!
そしたら確認のため、welcomeページにアクセスしてください。
で、右クリックして、「検証」をクリックしてください。(chromeで説明しています。)
すると、右とか下とかにツールが開きます。
で、
で、画像のアイコンをクリックして、「記事投稿」と表示されているところにカーソルを持っていって、クリックしてください。
すると、
はい、こんな感じで、
{{route('article.new')}}
と書いた箇所が
http://localhost:8080/public/article/new
と表示されてますね!
では、「記事投稿」をクリックしてリンク先にアクセスしてみてください。
hello world!!が表示されましたか?されていれば、リンクはちゃんと設定されているということです!
いい感じですよぉぉ!
さぁ少し長くなってきましたが、あともう少しお付き合いください。🕺
そしたら、先ほど作成したnew.blade.phpに、記事のタイトルと記事を投稿できるフォームなどを作成していきましょう!
new.blade.phpに書いたhello world!!を消して、以下をコピペしてください。
@extends('layouts.app')
@section('content')
<form action="#" method="post">
<input name="title" type="text">
<textarea name="content" cols="30" rows="10"></textarea>
<input type="submit">
</form>
@endsection
@extends('layouts.app')
これは、bladeの書き方で、resources/views/layouts/app.blade.phpを継承する記述です。
@section('content')
~~
@endsection
これは、app.blade.phpの
@yield('content')
と記載されている部分の内容を書く書き方になります。
<form action="#" method="post">
<input name="title" type="text">
<textarea name="content" cols="30" rows="10"></textarea>
<input type="submit">
</form>
これはフォームを作成する書き方になります。
ちょっとよくわからないかもしれませんが、今はふーんと思っていれば大丈夫です!
はい、そしたら、もう一度「記事投稿」をクリックしてみてください。
こんな感じのformが表示されましたね!
ひとまずformが作成できたので、保存用のアクションにリクエストを送ります!
(見た目はご自身で整えてください!html,cssで検索すればたくさんヒットするのでチャレンジしてみましょう!)
viewからcontrollerへrequestを送信
そしたらweb.phpを開いてください。
で、以下をコピペしてください。
Route::post('/article/create', 'ArticleController@create')->name('article.create');
今回はformタグでpostメソッドを指定しているので、httpリクエストはpostを指定しています。
ということで、ArticleControllerにcreateアクションを定義しましょう!
以下をArticleController.phpにコピペしてください。
public function create(Request $request)
{
return redirect('/');
}
はい、今回のアクションには引数(Request $request)を指定します。
controllerを作成した際、
use Illuminate\Http\Request;
とRequestクラスがuseされているので、Requestクラスのインスタンスを$requestという名前の変数で引数にとります。
はい、急に意味わかんないですね!私の語彙力の問題もありますが、上の文章で登場したワードを簡単に説明すると
- クラス: 犬で例えるなら「犬という概念」です。例えば、チワワを見て、「この動物はなんですか?」と聞かれたら、「犬」と答える感じです。つまり、頭の中で描く「犬」をクラスと呼びます。クラスはそのままでは使用できません。頭の中に「犬」を思い浮かべても、触ったりすることはできませんよね?
- インスタンス: クラスを実体化したものがインスタンスです。「犬クラス」で考えると、その辺を歩いている柴犬とかチワワとか、実際に触れる犬をインスタンスと呼びます。一度「犬」を思い浮かべてください。思い描いた「犬」は何してますか?尻尾振ってますか?何か食べてますか?はい、では、実際に犬は、今皆さんが思い浮かべたことができると思いますか?多分できますよね。何を当たり前のこと言ってんだと思うかもしれませんが、つまり、「犬という概念(クラス)」から生まれた「犬(インスタンス)」は、概念にあることを実際に実行できるということです。つまり、そういうことです!
- 変数: 情報(データ)の入れ物です。例えばみかんが入った箱を想像してください。そのみかんが入った箱が「変数」です。で、空の箱を想像してください。その空の箱が「変数」です。つまり、中に何かしら入ってても、入ってなくても、箱は全て変数ということです。
- 引数: アクションに渡すデータを引数と言います。自販機で例えると、「ジュースを外に出すアクション」で考えたらお金が必要ですよね。つまり、お金が引数になります。ただ、お金を投入するときは裸銭ですが、実際にアクションにたどり着くときは変数に変わっています。
???と思っている方!大丈夫です!特にクラス、インスタンスていう概念は、多分ですが、確実に正確に言葉にできる人はほとんどいません!(と思う!)だいたいこんな例えでしか説明できないと思います。
なので、気になった方は
について調べてみてください。
(なお、この概念というか言葉とかは、他のプログラミング言語でもほぼ同じです。(と思います))
そしたら続きいきます。
とりあえず
return redirect('/');
処理が終了したら、welcomeページにリダイレクトするようにします。(こう書けば、リダイレクトすることができます。)
ちょっと説明が長くなりましたが、早速リクエストを送信してみましょう!
先ほど作成したformのactionを以下のとおり書き換えてください。
<form action="{{route('article.create')}}" method="post">
で、「送信」をクリックしてみましょう。
はい、これはlaravelが用意したエラーページです。
これはlaravelがデフォルトで用意しているセキュリティ対策で、クロスサイトリクエストフォージェリ(csrf)を防ぐためのちゃんとした挙動ですので、安心してください。
クロスサイトリクエストフォージェリ(CSRF)とは、Webアプリケーションに存在する脆弱性、もしくはその脆弱性を利用した攻撃方法のことです。掲示板や問い合わせフォームなどを処理するWebアプリケーションが、本来拒否すべき他サイトからのリクエストを受信し処理してしまいます。
それでは、このエラーを回避するためにnew.blade.phpを修正しましょう!
@extends('layouts.app')
@section('content')
<form action="{{route('article.create')}}" method="post">
@csrf //←追加
<input name="title" type="text">
<textarea name="content" cols="30" rows="10"></textarea>
<input type="submit">
</form>
@endsection
はい、formの真下に@csrfと付け加えましょう。これだけで大丈夫です!
そしたら、もう一度「送信」をクリックしてみましょう!
welcomeページが表示されましたか?されていればちゃんとcreateアクションを通過しているということです。
さて、それではフォームに何か入力して、controllerで値を確認してみましょう!
適当に入力して、前回設定した
xdebugを起動してください。(まだ「送信」は押さないでください。また、
xdebugの操作については前回の記事を参照してください。)
で、createアクションにブレークポイント(赤い丸)を設定してください。
準備できたらブラウザに表示されている「送信ボタン」をクリックしてみてください。
止まりましたね!ちゃんとcreateアクションに処理が走ってますね!いい感じです!
で、変数と書かれたところに$requestという変数が表示されていると思いますので、中身を見てみましょう!
はい、$requestの中のrequestの中のparametersに
として、フォームに入力した内容が入ってきてますね!
_tokenは@csrfと書いた部分から送られたパラメータになります!
気になった方は、検証を使って確認してみてください!
よっしゃ!どんどんブログの記事投稿に近づいてきてますね!
ということで、今回はここまでにします!
次回はこの送られてきたパラメータを記事としてデータベースに保存します!
ようやくMVCのMの登場です!
記事投稿できるまで長くなりますが、ご容赦ください。
じゃ、おやすみなさい!