前回、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でページャー、記事の削除、編集を追加します。