Edited at
LaravelDay 23

laravel5.7 掲示板作成 チュートリアル

アドベントカレンダーLaravelを初めて書かせていただきました。

こちらは、昔書いたものを復刻したものです。

windowsの方はこちら

windows Laravel環境構築

https://qiita.com/homhom99/items/3161ed3eb8ea0e6ba14e

macの方はこちら

mac Laravel環境構築

https://qiita.com/homhom99/items/38bc4e4a02a66acead91



最低限の設定


\config\app.php

'timezone' => 'Asia/Tokyo',

'locale' => 'ja',



Controllerを作る

php artisan make:controller HelloController

ここを見てみましょう

できたファイルを編集してみましょう


\app\Http\Controllers\HelloController.php

    public function index()

{
$msg = 'hello';
return view('hello.index', ['msg' => $msg]);
}



ルーティングを設定する


\routes\web.php

Route::get('/hello', 'HelloController@index');



bladeを作成する


\resources\views\hello\index.blade.php

{{$msg}}


次のURLを確認してみましょう

http://localhost:8000/hello



@foreachを使う


\app\Http\Controllers\HelloController.php

    public function index()

{
$msgs = [
'hello',
'こんにちは',
'尓好'
];
return view('hello.index', ['msgs' => $msgs]);
}



bladeの中でforeachを使う


\resources\views\hello\index.blade.php

@foreach($msgs as $msg)

{{$msg}}<br>
@endforeach


Bladeを使わないとこんな書き方です

参考サイト

flatFlag

endforeachの書き方でHTML埋め込みもスッキリ!

https://www.flatflag.nir87.com/foreach-294#endforeachHTML



ほかはこういうのもあります

@if(bool)

// code
@endif

次とイコール

<?php if(boo) : ?>
// code
<?php endif; ?>

@php

// code
@endphp

次とイコール

<?php
// code
?>

他にはこんなものもあります

参考サイト

Laravel 5.7 Bladeテンプレート

https://readouble.com/laravel/5.7/ja/blade.html#introduction



DB作成

マイグレーションファイルを作成

DBの移行を簡単にするファイル。

ここでは、DBを作成するために使う。

php artisan make:migration create_article_table



マイグレーションファイルを編集


\database\migrations\2018_08_10_183909_create_article_table.php


<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticleTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::create('article', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->string('body');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/

public function down()
{
Schema::dropIfExists('article');
}
}




マイグレーション実行

php artisan migrate

DBが作られているかDB Browser for SQLiteで確認する

macは

mysql> show column from article;



サンプルデータを作る

seederファイルを作成。

サンプルデータを作れる。

php artisan make:seeder ArticleSeeder



\database\seeds\ArticleSeeder.php


<?php

use Illuminate\Database\Seeder;

class ArticleSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/

public function run()
{
// テーブル内のデータを一旦全削除
\Illuminate\Support\Facades\DB::table('article')->truncate();

// データのインサート
DB::table('article')->insert([
[
'user_id' => 2,
'title' => 'title1',
'body' => 'body1',
'created_at' => '2018-06-10 21:07:31',
'updated_at' => '2018-06-10 21:07:31'
],
[
'user_id' => 2,
'title' => 'title2',
'body' => 'body2',
'created_at' => '2018-06-10 21:07:31',
'updated_at' => '2018-06-10 21:07:31'
],
[
'user_id' => 2,
'title' => 'title3',
'body' => 'body3',
'created_at' => '2018-06-10 21:07:31',
'updated_at' => '2018-06-10 21:07:31'
]
]);
}
}




seederを登録する


\database\seeds\DatabaseSeeder.php

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/

public function run()
{
$this->call([
ArticleSeeder::class,
]);
}
}


seederを実行

php artisan db:seed

データができているか見てみましょう。

mac

select * from article;


モデルを作成

$ php artisan make:model Article

Articleモデルに、利用するテーブル名を追加


\app\Article.php

class Article extends Model

{
protected $table = 'article';
}



Controllerを作る

php artisan make:controller ArticleController


\app\Http\Controllers\ArticleController.php


// モデルを追加
use App\Article;

public function index()
{
// データベースから全データを取得
$article = Article::all();
// viewにデータを渡す
return view('article.index', ['articles' => $article]);
}




ルーティングを設定する


\routes\web.php

Route::get('/article', 'ArticleController@index');




bladeを作成する

次の場所にファイルを作成

\resources\views\article\index.blade.php


一旦ここでDBからデータが取れるか確認


\resources\views\article\index.blade.php

@foreach($articles as $article)

{{$article->title}}
{{$article->body}}
@endforeach

http://localhost:8000/article


errorになる場合

ヒント

DB設定を見直す

serverを一旦ストップ、再起動

キャッシュをクリアしてみる

$ php artisan config:clear

$ php artisan cache:clear


データを作成するメソッドを追加


\app\Http\Controllers\ArticleController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Article;
use Validator;

class ArticleController extends Controller
{
public function index()
{
$articles = Article::orderBy('id', 'desc')->get();
return view('article.index', ['articles' => $articles]);
}

public function add (Request $request)
{
// 保存の処理
$article = new Article;
$article->user_id = 1; // 今回は1固定
$article->title = $request->input('title');
$article->body = $request->input('body');
$article->save();

return redirect()->to('/article');
}



\routes\web.php

Route::post('/article/add', 'ArticleController@add');




bladeを作成

多いのでコピペしましょう。


\resources\views\layouts\common.blade.php

<html>

<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em" crossorigin="anonymous"></script>
<title>@yield('title')</title>
</head>
<body>
<div class="mx-auto" style="width: 600px; background-color: #2ff1d4; margin: 10px 10px">
<div class="container-fluid">
@yield('content')
</div>
</div>
</body>
</html>


少しだけ解説


タイトルをはめ込みます

<title>@yield('title')</title>        


設定したコンテンツをはめ込みます

@yield('content')



\resources\views\article\index.blade.php

@extends('layouts.common')

@section('title', '掲示板')
@section('content')
<div class="row">
<div class="col-sm-12">
<form method="POST" action="/article/add">
<div class="form-group">
{{ csrf_field() }}
<p class="ext-monospace">タイトル</p><input type="text" name="title" class="form-control">
<p class="ext-monospace">本文</p><input type="text" name="body" class="form-control">
<br><input type="submit" value="投稿" class="btn btn-default">
</div>
</form>

</div>
</div>
<div class="mx-auto" style="width: 450px;">
<div class="row">
<div class="col-sm-12">
@foreach($articles as $article)
<div class="card border-primary mb-4" style="max-width: 30rem;">
<div class="card-body text-primary">
<h5 class="card-title">{{$article->title}}</h5>
<p class="card-text">{{$article->body}} </p>
</div>
</div>
@endforeach
</div>
</div>
</div>
@endsection




親bladeとの関係性を設定します。

@extends('layouts.common')


タイトルを設定できます

@section('title', '掲示板')


はめ込む部品を書きます。

@section('content')

//code
@endsection

コメントを追加してみよう

http://localhost:8000/article



削除機能をつける


\resources\views\article\index.blade.php


<p class="card-text">{{$article->body}}</p>
// この下に入れる
<form method="post" action="/article/delete/{{$article->id}}">
{{ csrf_field() }}
<input type="submit" value="削除" class="btn btn-danger btn-sm" onclick='return confirm("君は本当に削除するつもりかい?");'>
</form>


Controllerに削除メソッドを追加


\app\Http\Controllers\ArticleController.php

public function delete (Request $request)

{
Article::find($request->id)->delete();
return redirect('/article');
}


ルートを設定し、deleteメソッドを起動させる。


\routes\web.php

Route::post('/article/delete/{id}', 'ArticleController@delete');


削除できるか確認してみよう

http://localhost:8000/article



Validate機能を設定する

保存処理の前にValidateの設定を書きます。


\app\Http\Controllers\ArticleController.php


// Validateをインポート
use Validator;

// 省略

public function add (Request $request)
{
// Validation
// 入力情報の取得
$inputs = $request->all();

// ルールを設定
$rules = [
'title' => 'required|max:15',
'body' => 'required|max:256'
];

// エラーメッセージを設定
$messages = [
'title.required' => 'タイトルは必須だよ',
'title.max' => 'タイトルは15文字以内だよ',
'body.required' => '本文は必須だよ',
'body.max' => '本文は256文字以内だよ'
];

$validation = Validator::make($inputs, $rules, $messages);

if ($validation->fails()){
return redirect()->back()->withErrors($validation->errors())->withInput();
}

// 保存の処理
$article = new Article;
$article->user_id = 1; // 今回は1固定
$article->title = $request->input('title');
$article->body = $request->input('body');
$article->save();

return redirect()->to('/article');
}




bladeを修正する

ここもコピペしよう


\resources\views\article\index.blade.php

<div class="row">

<div class="col-sm-12">
<form method="POST" action="/article/add">
<div class="form-group">
{{ csrf_field() }}
<p class="ext-monospace">タイトル</p>
<input type="text" name="title" class="form-control @if ($errors->has('title')) is-invalid @endif" value="{{old('title')}}">
@if ($errors->has('title'))
<span class="invalid-feedback">{{ $errors->first('title') }}</span>
@endif

<p class="ext-monospace">本文</p>
<input type="text" name="body" class=form-control value="{{old('body')}}">
@if ($errors->has('body'))
<span class="invalid-feedback">{{ $errors->first('body') }}</span>
@endif

<br><input type="submit" value="投稿" class="btn btn-default">
</div>
</form>

</div>
</div>


Validationが効いているかためしてみよう



参考サイト

Laravel 5.7 TOC

https://readouble.com/laravel/5.7/ja/