前回、Laravelプロジェクトを作成ました。
今回はプロジェクトに簡単な掲示板(記事一覧、記事投稿、コメント追加、記事の絞り込み)を作成します。
参考サイト
・Yaimapp(https://blog.yaimapp.net/post/112032489660/laravel5-%E3%81%A7%E6%8E%B2%E7%A4%BA%E6%9D%BF%E4%BD%9C%E6%88%90)
・manablog(https://manablog.org/laravel_bulletin_board/)
手順
1. データベース準備とLaravelからの接続設定
2. データベースの構造設計とリレーション設定
3. 機能の実装(コントローラーの作成)
4. 見た目の作成(ビューの作成)
5. 3と4を機能ごとに繰り返す()
1. データベース準備とLaravelからの接続設定
dbを下記の内容で設定した場合
host:localhost
dbの名前:test
dbのユーザー名:test
パスワード:6RtgFcRI7J6k0sFT
.envファイルに下記を記述
DB_HOST=localhost DB_DATABASE=test DB_USERNAME=test DB_PASSWORD=6RtgFcRI7J6k0sFT
2. データベースの構造設計とリレーション設定
testに3つのテーブルを作成します。
・記事用のposts
・記事のカテゴリ―用のcategories(一つの記事は一つのカテゴリに属している)
・記事に対するコメント用のcomments(一つの記事は複数のコメントをもつ)
上記の関係をLaravelに記述していきます。
コマンドプロンプト上で、プロジェクトファイルに移動。
cd C:\xampp\htdocs\test
その後、posts、categories、commentsを作成。
php artisan make:migration create_posts_table php artisan make:migration create_categories_table php artisan make:migration create_comments_table
detabase/migrations/…..create_posts_table.php
detabase/migrations/…..create_categories_table.php
detabase/migrations/…..create_comments_table.php
の3ファイルが作成されます。
detabase/migrations/…..create_posts_table.phpを修正します。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('cat_id');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
detabase/migrations/…..create_categories_table.phpを修正します。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
}
detabase/migrations/…..create_comments_table.phpを修正します。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCommentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('post_id');
$table->string('commenter');
$table->text('comment');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
}
修正したマイグレーションを実行し、データベースにテーブルを作成します。
php artisan migrate
エラーがでず、データーベースに作成したテーブルが定義されていればOKです。
筆者の場合、Laravelをインストールした時にデフォルトで作成されいるマイグレーションファイルでエラーが発生したので、余計なマイグレーションファイルを削除して、再度マイグレーションを実行しました。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
次は、Laravel上でリレーションの設定を記述します。
php artisan make:model Post php artisan make:model Comment php artisan make:model Category
app/Post.php
app/Comment.php
app/Category.php
の3ファイルが作成されます。
app/Post.phpにリレーションを記述。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function Comment() {
// 一つの記事は複数のコメントをもつ
return $this->hasMany('App\Comment', 'post_id');
}
public function Category(){
// 一つの記事は一つのカテゴリに属している
return $this->belongsTo('App\Category', 'cat_id');
}
}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
リレーションの記述が完了したので、ダミーデータを作成し、データベースに登録します。
detabase/seeds/PostCommentSeeder.phpに下記ファイルを作成します。
<?php
use Illuminate\Database\Seeder;
class PostCommentSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$content = 'この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。';
$commentdammy = 'コメントです。';
for( $i = 1 ; $i <= 10 ; $i++) {
$post = new App\Post;
$post->title = "$i 番目の投稿";
$post->content = $content;
$post->cat_id = 1;
$post->save();
$maxComments = mt_rand(3, 15);
for ($j=0; $j <= $maxComments; $j++) {
$comment = new App\Comment;
$comment->commenter = 'テストユーザ';
$comment->comment = $commentdammy;
$post->comments()->save($comment);
}
}
$cat1 = new App\Category;
$cat1->name = "カテゴリーその1";
$cat1->save();
$cat2 = new App\Category;
$cat2->name = "カテゴリーその2";
$cat2->save();
}
}
シーダーファイルを実行。
php artisan db:seed --class=PostCommentSeeder
エラーが出る場合は
composer dump-autoload
を実行したのち、再度シーダーを実行してください。
成功すれば、データーベースにダミーデータが保存されています。
3,4 機能の実装
<記事投稿機能作成>
記事投稿機能を作成していきます。
php artisan make:controller PostsController
app/Http/Controllers/PostsController.phpが作成されます。
①投稿一覧ページ
routes/web.php編集
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| 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');
});
Route::resource('bbs', 'PostsController');//bbsにアクセスした際にPostsControllerに処理させる
app/Http/Controllers/PostsController.php編集
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();//全記事取得
return view('bbs.index')->with('posts', $posts);//index.blade.phpに値をわたす
}
}
resources/viwes/layouts/default.blade.php編集
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<title>Laravelの掲示板</title>
</head>
<body>
@yield('content')
</body>
</html>
resources/viwes/bbs/index.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
@foreach($posts as $post)
<h2>タイトル:{{ $post->title }}
<small>投稿日:{{ date("Y年 m月 d日",strtotime($post->created_at)) }}</small>
</h2>
<p>カテゴリー:{{ $post->category->name }}</p>
<p>
<?php
echo $post->comments->count();
?>
件のコメント</p>
<p>{{ $post->content }}</p>
<p>{{ link_to("/bbs/{$post->id}", '続きを読む', array('class' => 'btn btn-primary')) }}</p>
@endforeach
</div>
@stop
http://localhost/test/public/bbsにアクセスするとこのような画面が表示されればOK
エラーが出た場合は、Laravelのバージョン違いによるlink_toのサポート切れだと思われます。(筆者もエラーがでました。)
link_toを使えるように、composerを使用して外部からパッケージをインストールします。
link_toを使用するにはilluminate/htmlやlaravelcollective/htmlを使えばいけると記事が散見されました。ただ、illuminate/htmlはアップデートが終了しているからやめた方が良いよ的な記事も見たので(嘘だったらごめんなさい)、laravelcollective/htmlを使用します。
https://laravelcollective.com/docs/6.0/html
コマンドプロンプトで以下を実行。
composer require laravelcollective/html
これで、link_toが使えるようになり、エラーが解消されると思います。
エラーが出る場合はcomposer update後に再度ページを確認してください。
これでもエラーで出る場合は、違う箇所に問題があるかもです。
composer update
②続きを読むページを作成
app/Http/Controllers/PostsController.php編集
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();//全記事取得
return view('bbs.index')->with('posts', $posts);//index.blade.phpに値をわたす
}
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return View('bbs.single')->with('post', $post);
}
}
resources/viwes/bbs/single.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
<h2>タイトル:{{ $post->title }}
<small>投稿日:{{ date("Y年 m月 d日",strtotime($post->created_at)) }}</small>
</h2>
<p>カテゴリー:{{ $post->category->name }}</p>
<p>{{ $post->content }}</p>
<hr />
<div>
<p>{{ link_to("/bbs", '一覧に戻る', array('class' => 'btn btn-primary')) }}</p>
</div>
<h3>コメント一覧</h3>
<p>
<?php
echo $post->comments->count();
?>
件のコメント</p>
<br />
@foreach($post->comments as $single_comment)
<h4>{{ $single_comment->commenter }}</h4>
<p>{{ $single_comment->comment }}</p><br />
@endforeach
</div>
@stop
http://localhost/test/public/bbsから続きを読むを押すことで、記事の詳細ページがひらきます。
③記事投稿機能
<表示機能>
resources/viwes/bbs/index.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
<div class="">
<p>{{ link_to("/bbs/create", '新規作成', array('class' => 'btn btn-primary')) }}</p>
</div>
@foreach($posts as $post)
<h2>タイトル:{{ $post->title }}
<small>投稿日:{{ date("Y年 m月 d日",strtotime($post->created_at)) }}</small>
</h2>
<p>カテゴリー:{{ $post->category->name }}</p>
<p>
<?php
echo $post->comments->count();
?>
件のコメント</p>
<p>{{ $post->content }}</p>
<p>{{ link_to("/bbs/{$post->id}", '続きを読む', array('class' => 'btn btn-primary')) }}</p>
@endforeach
</div>
@stop
app/Http/Controllers/PostsController.php編集
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();//全記事取得
return view('bbs.index')->with('posts', $posts);//index.blade.phpに値をわたす
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('bbs.create');
}
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return View('bbs.single')->with('post', $post);
}
}
resources/viwes/bbs/create.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
<h1>投稿ページ</h1>
{{-- 投稿完了時にフラッシュメッセージを表示 --}}
@if(Session::has('message'))
<div class="bg-info">
<p>{{ Session::get('message') }}</p>
</div>
@endif
{{-- エラーメッセージの表示 --}}
@foreach($errors->all() as $message)
<p class="bg-danger">{{ $message }}</p>
@endforeach
{{ Form::open(['route' => 'bbs.store'], array('class' => 'form')) }}
<div class="form-group">
<label for="title" class="">タイトル</label>
<div class="">
{{ Form::text('title', null, array('class' => '')) }}
</div>
</div>
<div class="form-group">
<label for="cat_id" class="">カテゴリー</label>
<div class="">
<select name="cat_id" type="text" class="">
<option></option>
<option value="1" name="1">カテゴリーその1</option>
<option value="2" name="2">カテゴリーその2</option>
</select>
</div>
</div>
<div class="form-group">
<label for="content" class="">本文</label>
<div class="">
{{ Form::textarea('content', null, array('class' => '')) }}
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">投稿</button>
</div>
{{ Form::close() }}
<a href="{{ action('PostsController@index') }}" class="btn btn-primary">一覧に戻る</a>
</div>
@stop
http://localhost/test/public/bbs/createにアクセス
<dbへの登録とバリデーション機能>
app/Http/Controllers/PostsController.php編集
use Illuminate\Support\Facades\Validator;
use Redirect;
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use Illuminate\Support\Facades\Validator;
use Redirect;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();//全記事取得
return view('bbs.index')->with('posts', $posts);//index.blade.phpに値をわたす
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('bbs.create');
}
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return View('bbs.single')->with('post', $post);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$rules = [
'title' => 'required',
'content'=>'required',
'cat_id' => 'required',
];
$messages = array(
'title.required' => 'タイトルを正しく入力してください。',
'content.required' => '本文を正しく入力してください。',
'cat_id.required' => 'カテゴリーを選択してください。',
);
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->passes()) {
$post = new Post;
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->cat_id = $request->input('cat_id');
$post->save();
return Redirect::back()
->with('message', '投稿が完了しました。');
}else{
return Redirect::back()
->withErrors($validator)
->withInput();
}
}
}
空欄で投稿を押すと、エラーが返ってくる。必須項目を入力すれば、記事を登録することができる。
④カテゴリー別による記事の表示
resources/viwes/bbs/index.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
<div class="">
<p>{{ link_to("/bbs/create", '新規作成', array('class' => 'btn btn-primary')) }}</p>
</div>
@foreach($posts as $post)
<h2>タイトル:{{ $post->title }}
<small>投稿日:{{ date("Y年 m月 d日",strtotime($post->created_at)) }}</small>
</h2>
<p>カテゴリー:{!! link_to("/bbs/category/{$post->category->id}", $post->category->name, array('class' => '')) !!}</p>
<p>
<?php
echo $post->comments->count();
?>
件のコメント</p>
<p>{{ $post->content }}</p>
<p>{{ link_to("/bbs/{$post->id}", '続きを読む', array('class' => 'btn btn-primary')) }}</p>
@endforeach
</div>
@stop
routes/web.php編集
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| 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');
});
Route::resource('bbs', 'PostsController');//bbsにアクセスした際にPostsControllerに処理させる
Route::get('bbs/category/{id}', 'PostsController@showCategory');
app/Http/Controllers/PostsController.php編集
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use Illuminate\Support\Facades\Validator;
use Redirect;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::all();//全記事取得
return view('bbs.index')->with('posts', $posts);//index.blade.phpに値をわたす
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('bbs.create');
}
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return View('bbs.single')->with('post', $post);
}
public function showCategory($id)
{
$category_posts = Post::where('cat_id', $id)->get();
return view('bbs.category')
->with('category_posts', $category_posts);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$rules = [
'title' => 'required',
'content'=>'required',
'cat_id' => 'required',
];
$messages = array(
'title.required' => 'タイトルを正しく入力してください。',
'content.required' => '本文を正しく入力してください。',
'cat_id.required' => 'カテゴリーを選択してください。',
);
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->passes()) {
$post = new Post;
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->cat_id = $request->input('cat_id');
$post->save();
return Redirect::back()
->with('message', '投稿が完了しました。');
}else{
return Redirect::back()
->withErrors($validator)
->withInput();
}
}
}
http://localhost/test/public/bbsのカテゴリーを押すと、カテゴリーごとに記事を絞り込んで表示する。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
<記事へのコメント機能作成>
コメント機能機能を作成していきます。
php artisan make:controller CommentsController
app/Http/Controllers/CommentsController.phpが作成されます。
routes/web.php編集
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| 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');
});
Route::resource('bbs', 'PostsController');//bbsにアクセスした際にPostsControllerに処理させる
Route::get('bbs/category/{id}', 'PostsController@showCategory');
Route::resource('comment', 'CommentsController');
app/Http/Controllers/CommentsController.php編集
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Comment;
use Illuminate\Support\Facades\Validator;
use Redirect;
class CommentsController extends Controller
{
public function store(Request $request)
{
$rules = [
'commenter' => 'required',
'comment'=>'required',
];
$messages = array(
'commenter.required' => 'タイトルを正しく入力してください。',
'comment.required' => '本文を正しく入力してください。',
);
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->passes()) {
$comment = new Comment;
$comment->commenter = $request->input('commenter');
$comment->comment = $request->input('comment');
$comment->post_id = $request->input('post_id');
$comment->save();
return Redirect::back()
->with('message', '投稿が完了しました。');
}else{
return Redirect::back()
->withErrors($validator)
->withInput();
}
}
}
resources/viwes/bbs/single.blade.php編集
@extends('layouts.default')
@section('content')
<div class="col-xs-8 col-xs-offset-2">
<h2>タイトル:{{ $post->title }}
<small>投稿日:{{ date("Y年 m月 d日",strtotime($post->created_at)) }}</small>
</h2>
<p>カテゴリー:{{ $post->category->name }}</p>
<p>{{ $post->content }}</p>
<hr />
<div>
<p>{{ link_to("/bbs", '一覧に戻る', array('class' => 'btn btn-primary')) }}</p>
</div>
<h3>コメント一覧</h3>
<p>
<?php
echo $post->comments->count();
?>
件のコメント</p>
<br />
@foreach($post->comments as $single_comment)
<h4>{{ $single_comment->commenter }}</h4>
<p>{{ $single_comment->comment }}</p><br />
@endforeach
<h3>コメントを投稿する</h3>
{{-- 投稿完了時にフラッシュメッセージを表示 --}}
@if(Session::has('message'))
<div class="bg-info">
<p>{{ Session::get('message') }}</p>
</div>
@endif
{{-- エラーメッセージの表示 --}}
@foreach($errors->all() as $message)
<p class="bg-danger">{{ $message }}</p>
@endforeach
{{ Form::open(['route' => 'comment.store'], array('class' => 'form')) }}
<div class="form-group">
<label for="commenter" class="">名前</label>
<div class="">
{{ Form::text('commenter', null, array('class' => '')) }}
</div>
</div>
<div class="form-group">
<label for="comment" class="">コメント</label>
<div class="">
{{ Form::textarea('comment', null, array('class' => '')) }}
</div>
</div>
{{ Form::hidden('post_id', $post->id) }}
<div class="form-group">
<button type="submit" class="btn btn-primary">投稿する</button>
</div>
{{ Form::close() }}
</div>
@stop
これで記事の詳細ページの下部にコメント投稿部分が追加されました。
長くなりましたが、以上です。
パート2でページャー、記事の削除、編集を追加します。