今回は、Laravel6を使って、サイトに投稿フォームを自作し、フォームから送信された投稿をデーターベースに保存するチュートリアルをやっていきます。
前回までにブレードでウェブページを作る基礎をやってきました。
1. Laravel6チュートリアル超初心者向け:サイトを表示させて仕組みを理解しよう!
2. Laravel6チュートリアル初心者向け:bladeでウェブページを作ってみよう!
3. Laravel6チュートリアル初心者向け:ブレード継承で複数ページを作ってみよう!
このような、サイト全体の基礎レイアウトを作ったわけですが、じゃあ仮にブログや口コミサイトを作るとして、肝心の投稿ってどうやるの?って疑問がありますよね。
それは、投稿フォームを自作して、投稿するんです。
前回までのチュートリアルでは、ブレードとルートしか使いませんでしたが、
投稿機能を付けるとなると、ここで、コントローラーとデータベース(+モデル)も必要になってきます。
というわけで、このフォーム作成から保存までを一緒にやって、使いこなせるようになりましょう!
Laravel6チュートリアル初心者向け:フォームを作成し投稿を保存してみよう!
このチュートリアルは、Laravelプロジェクトは作成済みという前提で話を進めていきます。
Laravelプロジェクト(Laravelサイト自体)がまだ無い場合は、このチュートリアルを見て、まず作ってね↓
ここからは、このような流れで、入力フォーム作成から、投稿の保存までをやっていきます。
- ブレードに入力フォームを作成
- コントローラーを作成
- ルートを設定
- データーベース作成
- モデル作成とマイグレーション
- コントローラーに保存命令を書く
ブレードに入力フォームを作成する
では、何はともあれ、入力フォームを作成しましょう。
今回は、ブログ風の投稿ができるように、タイトルと本文の入力欄を作ってみましょう。
空のテキストエディタを開いて、下のコードをコピペしてください。
コピーしました
コピー
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>newsite</title>
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/style.css') }}">
</head>
<body>
<div class="wrapper">
<div class="header"><h1>投稿ページ</h1></div>
<div class="content_wrapper">
<div class="content2">
<form action="/newpostsend" method="post">
@csrf
<p>タイトル</p>
<input type="text" name="title" class="formtitle">
<p> </p>
<p>本文</p>
<textarea name="main" cols="40" rows="10"></textarea>
<p> </p>
<input type="submit" class="submitbtn">
</form>
</div>
</div>
</div>
</body>
</html>
そして、resources\viewsフォルダにform.blade.phpという名前で保存してください。
ここでフォーム部分を解説します。
まず、HTMLで<form>タグを作ります。actionに書かれているのは、URLで、この/newpostsendというURLに入力されたデータを送信するという意味です。
次の@csrfですが、これはなりすましアクセスなどを防ぐコードで、Laravelにフォームを設置する時は必ずこの@csrfを付けないと、フォームが動かないようになってます。
次に<input>ですが、これがタイトル入力欄です。
その下の<textarea>が本文を入力する欄です。
最後の<input>が送信ボタンです。
<input>と<textarea>に指定したnameというのは、後でデータベースのカラム名として使います。
CSSに追記する
次にpublic\cssフォルダのstyle.cssを開きます。
そして、以下を追記して、保存してください。
前回のチュートリアルをやってる場合コピーしました
コピー
.content_wrapper{
width: 1000px;
min-height:500px;
text-align: center;
}
.content2{
display: inline-block;
text-align: left;
width:690px;
min-height:500px;
background-color: #ffffff;
border: 5px solid #707aff;
border-radius: 10px;
margin: 20px 0;
padding: 10px;
}
前回のチュートリアルをやってない場合は以下も加えて追記
コピーしました
コピー
/* CSS Reset */
*,*::before,*::after{box-sizing:border-box}ul[class],ol[class]{padding:0}body,h1,h2,h3,h4,p,ul[class],ol[class],figure,blockquote,dl,dd{margin:0}body{min-height:100vh;scroll-behavior:smooth;text-rendering:optimizeSpeed;line-height:1.5}ul[class],ol[class]{list-style:none}a:not([class]){text-decoration-skip-ink:auto}img{max-width:100%;display:block}article>*+*{margin-top:1em}input,button,textarea,select{font:inherit}img:not([alt]){filter:blur(10px)}@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}
/* iOS デフォルトスタイルのリセット */
input[type="submit"],
input[type="button"] {
border-radius: 0;
-webkit-box-sizing: content-box;
-webkit-appearance: button;
appearance: button;
border: none;
box-sizing: border-box;
cursor: pointer;
}
input[type="submit"]::-webkit-search-decoration,
input[type="button"]::-webkit-search-decoration {
display: none;
}
input[type="submit"]::focus,
input[type="button"]::focus {
outline-offset: -2px;
}
.define-text1 br{
margin-bottom: 10px;
}
html, body {
background-color: #fff;
color: #3c4447;
font-family: 'ヒラギノ角ゴ ProN', 'Hiragino Kaku Gothic ProN', 'メイリオ', Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif;
font-weight: 200;
height: 100vh;
/* viewpointに対して100%の意味 */
}
h3{
font-weight: 200;
}
b{font-weight: bold;}
hr{margin: 20px 0;}
.wrapper{
width: 1000px;
background-color: #20f3f3;
min-height:700px;
/* border: 1px solid #ccc; */
margin: 0 auto;
}
.header{
background-color: #707aff;
margin: 0 0 10 0px;
height: 100px;
padding: 20px;
}
.sidebar{
margin:20px;
background-color: #ffffff;
border: 2px solid #707aff;
border-radius: 10px;
width: 250px;
min-height:500px;
float: right;
padding: 10px;
}
.content{
text-align: center;
width:690px;
min-height:500px;
background-color: #ffffff;
border: 5px solid #707aff;
border-radius: 10px;
margin: 20px;
padding: 10px;
}
.footer{
background-color: #707aff;
height: 80px;
text-align: center;
padding: 10px;
}
コントローラーを作成する
次にコントローラーを作成します。コントローラーは、このフォームに入力された投稿をデータベースに保存したり、逆にデータベースから出したりする、裏方で仕事するファイルです。
コマンドプロンプト(shell/ターミナル)を立ち上げてください。
- cdでLaravelプロジェクトフォルダ(サイトのフォルダ)まで移動します。例:cd D:\XAMPP\htdocs\newsite と入力、Enter。
- php artisan make:controller FormController と入力、Enterする。
app\Http\Controllersフォルダに新しいコントローラーが作成されてるはずです。
そして、このFormController.phpをテキストエディタで開きます。
このclassの波括弧内の//を消して、画像の黄枠の部分を追記します。
コピーしました
コピー
public function postpage (Request $request){
return view ('form');
}
public function savenew (Request $request){
//
}
このコードの意味は後半で解説します。
そのまま、上書き保存してください。
ルートを設定する
次にroutes\web.phpを開きます。
以下の2つのRouteを追記し、上書き保存します。
コピーしました
コピー
// 投稿ページを表示
Route::get('/create', 'FormController@postpage');
// 投稿をコントローラーに送信
Route::post('/newpostsend', 'FormController@savenew');
まず、上のRoute::getですが、これは/createというURLにアクセスしたら、FormControllerに今作成したfunction postpageを呼び出すという意味です。
下のRoute::postですが、これは /newpostsendというURLにフォーム送信があったら、FormControllerのfunction savenewを呼び出すという意味です。
例えば、/createというURLにアクセスがあると、web.phpによって、このpublic function postpageというメソッド(機能)が呼び出されます。で、ここには、return view ('form')と書きました。これは「form.blade.phpをビュー(ブラウザ表示)として返す」という意味です。
つまり、/createにアクセスがあると、form.blade.phpが表示されるって事です。
前回までのチュートリアルでは、
この画像のように、直接functionをweb.phpに書いてました。
今回はコントローラーに同じ記述をしてるというわけです。
今回からは、データーベースとのやり取りも含まれてくるのが理由の1つ。
あとコントローラーを介す事で、例えばログインした人のみ投稿フォームのページに飛ばしたい時に、ログインページを挟んだりとか、応用が効くようになるからなんだ。
ここで、一度、ブラウザで表示できるか確認するために、コマンドプロンプトに php artisan serve と入力、Enterして、http://localhost:8000/create にアクセスしてみましょう。
このように、表示されてればOKです。
ただ、現状、この入力フォームに何か書いて投稿しても、エラーが起こるだけです。
というのも、まだこの投稿を保存するデータベースを作成していないですし、コントローラーにも命令を書いてません。
というわけで、ここからデーターベース作成とマイグレーション+モデルの作成をやっていきます。
データベース作成
先程の図で簡単に解説しましたが、フォームに入力されたデータというのは、データベースという所に保存されます。
データベースは、図のように、エクセルのようになっていて、フォームの欄ごとに整頓して保存できるようになっています。
このデータベース自体をまず作成していきます。
まず、phpMyAdminを開きます。
XAMPPを使ってる場合は、MySQLをStart状態にしたうえで、Adminをクリックすると開きます。
レンタルサーバー上の場合は、レンタルサーバーのサイトでphpMyAdminがあるはずなので、ログインしてください。
phpMyAdminのトップページの左サイドバーに「新規作成」というのがあるはずなので、それをクリックします。
画像のように「データベースを作成する」画面で、データベース名を入力します。データベース名は基本的にはサイト名(Laravelプロジェクトフォルダと同じ名前)にしとくと良いでしょう。全部小文字にしとくとタイピングミスなどでバグが出る事も防げるので良いでしょう。
文字コードは、utf8mb4_general_ciを選び、作成ボタンを押せば、データベースができます。
.envにデータベースへのアクセス権を書き込む
次に、Laravelプロジェクトフォルダ(サイトのフォルダ)に入っている.envというファイルをテキストエディタで開きます。
9行目辺りから、データベースへのアクセス(ログイン)に必要な情報になってます。
まず、DB_DATABASEを今付けたデータベースに変えます。
DB_USERNAMEとDB_PASSWORDを自分でphpMyAdminに設定している場合は、それを入力します。デフォルトなら、root でDB_PASSWORD部分は空欄で大丈夫です。
最後に.envを上書き保存してください。
モデルの作成とマイグレーション
次に、モデル(Model)とマイグレーションファイルの作成をします。
では、コマンドプロンプト(Shell/ターミナル)を開いてください。
先程ブラウザ表示のために php artisan serve してる場合は、そのウィンドウはもう入力できないので、開きっぱなしにして、新しいウィンドウを開いてください。(単純にもう一回コマンドプロンプトを起動すればいいだけです)。
cdで、Laravelプロジェクトフォルダまで移動し、
php artisan make:model Form -m
と入力、Enterしてください。
このコマンドを使うと、まずappフォルダ内にForm.phpというModelが作成されます。
それと同時に、database\migrationsフォルダに、~create_forms_table.phpというのが追加されてるはずです。
先程のコマンドはモデル作成コマンドなんですが、最後に-mと付けた事で、マイグレーションファイルも同時に作成されています。
マイグレーションファイルというのは、データーベースに新たなテーブルやカラムを追加するためのファイルです。(詳しくは下の記事参照)
→LaravelのMigrationとは?初心者でも図解で面白いほどよく分かる!
では、このcreate_forms_table.phpをテキストエディタで開いてください。
画像の黄枠の2行をschema::createの{ }内に追加し、上書き保存してください。
コピーしました
コピー
$table->string('title')->nullable();
$table->longtext('main')->nullable();
まず、このcreate_forms_table.php自体によって、formsというテーブルがデーターベースに作成されます。
その中に、今書いた、title, mainという2つのカラムが追加されます。
さきほどフォームを作った際、
画像の赤線のように、タイトル入力欄のnameはtitle、本文入力欄には、mainと名付けました。
そう、これと対応するように、同じ名前のカラムをデーターベースに作るわけです。
$table->string('title')->nullable();
$table->longtext('main')->nullable();
のstringというのが文字列を意味してます。ただ、stringは文字数制限があり、あまり長い文章は入り切らないので、本文欄はlongtextという長文の文字列に対応したカラムを作成するように指定しています。
後ろのnullable()というのは、「フォームが空で送信されても保存してOK」という意味です。空欄のまま送信された場合、エラーを返したい場合は、->nullable()部分をなしにすればOKです。
より詳しくはマイグレーションの記事で解説してます。
では、上書き保存したこのマイグレーションファイルを実際にデーターベースに反映させましょう。
コマンドプロンプトで、先程の続きで、
php artisan migrate
と入力、Enterしてください。
画像のように、successfullyと出れば成功です。
うまく行かない場合は、
- cdで正しい場所に移動してない
- .envのログイン情報が間違っている
- マイグレーションファイルに間違いがある
などが考えられます。
では、実際にphpMyAdminを開いてみてください。
newsiteデーターベースをクリックすると、formsというテーブルが加えられてるはずです。それをまたクリックすると、
title, mainというカラムが生成されています。
無事データーベースの設定が完了しました。
後は、コントローラーに命令を書けば、フォームで入力した投稿をこのデーターベースに保存できるようになります。
(もし今回作成した新データーベースではなく、既存のすでに入力データがあるデーターベースを使ってこのチュートリアルをやってる場合は、以下の事はよく理解してないならやらないでください。過去のデータが消えてしまう可能性があります。)
そんな時は焦らず、
php artisan migrate:rollback
って、コマンドプロンプトに入力してEnterしてみて。今のマイグレーションが取り消しされて、データーベースに作られた失敗テーブルが消えるから。これでもう一回マイグレーションし直せばOKだよ。
もっと詳しくは↓
コントローラーからデーターベースへの命令を書こう!
先程の、app\Http\Controllers\FormController.phpを開きます。
黄色の部分を追記します。まず、useの所に、
use App\Form;
と追記します。
これは、先程作成したFormモデルの場所を示してます。
→Laravelのuseとは?超初心者向けにシンプルに分かりやすく解説
次に public function saveの{ }内の//を消し、以下を記入します。
コピーしました
コピー
$post = new Form;
$post->title = $request->title;
$post->main = $request->main;
$post->save();
return redirect ('/create');
解説すると、まず、FormというのはFormモデルの事です。Formモデル=formsテーブルです。
このformsテーブルに新規で書き込むので、newと宣言してると考えてください。
次の行で、$request->titleというのがありますよね。
このrequestというのが、送信されたフォームのデータを意味してます。
→LaravelのControllerのRequestとは?初心者でも図解と例でバッチリ分かる!
つまり、$request->title(フォームで送信されたタイトル)を、$post->title(formsテーブルのtitleカラムに新規で保存する)という意味になってるんです。
次の行も同じで、最後に、$post->save();でデーターベースに保存が実行されます。
そして、保存した後どうするか?
元の投稿フォームのページにリダイレクトしたいので、return redirect ('/create');
と書きます。
投稿がデーターベースに保存されるかやってみよう!
では、投稿がちゃんとデーターベースに保存されるかやってみましょう。
まず、コマンドプロンプトに
php artisan config:cache
と入力、Enterしてください。
これはキャッシュを消すコマンドです。
キャッシュが残ってると、うまくフォームが作動しないので、念の為消しておきます。
次に
http://localhost:8000/create
にブラウザからアクセスしてみてください。
画像のように、適当に入力して、送信してみてください。
その後、同じページにリダイレクトされたはずです。
→419 Page Expired とLaravelでフォーム送信時に出た時の対処法
そして、phpMyAdminを開いてください。
formsテーブルをクリックすると、黄枠のように、入力したデータ、作成日、idが入ってるはずです。
これでデーターベースへ保存する事ができました!
うまく行きましたか?
次のチュートリアルでは、このデーターベースに保存した投稿を実際にサイトに表示する方法をやっていきます。
→Laravel6チュートリアル初心者向け:データベースの値を取得して表示してみよう