0
0

Laravel初心者が掲示板作る【Laravel 8.x】

Last updated at Posted at 2024-08-27

こちらの記事を参考にしてLaravel初心者がつまづいた所をまとめてみる。

バージョン

Laravel version
8.83.27

PHP version
7.4.33

MuSQL version
5.7.39

MAMP version
6.9

進捗

現在、
投稿記事を表示するためのコントローラーをつくっていく
の章の
投稿一覧の表示ページを作成する
でつまづいている。

2024.8.1

Seederが動かない

ターミナル
$XXX bbc % php artisan db:seed
Database seeding completed successfully.

とりあえず、php artisan db:seed
php artisan migrateみたいに
マイグレーションファイルやシーダーファイルも
一括で読んでくれるものだと勘違い。
実際はデフォルトだとDatabaseSeederクラスを実行するものだから、
Database seeding completed successfully.が表示されちゃった。
特定ファイルを実行したい場合は--classオプションを使う。

↓コマンド書き換えて実行

ターミナル
$XXX bbc % php artisan db:seed --class=PostCommentSeeder

   Error 

  Class 'Seeder' not found

  at database/seeders/PostCommentSeeder.php:3
      1▕ <?php
      2▕ 
  ➜   3▕ class PostCommentSeeder extends Seeder{
      4▕ 
      5▕ public function run(){
      6▕ 	$content = 'この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。';
      7▕ 
      8▕ 	$commentdammy = 'コメントダミーです。ダミーコメントだよ。';
      9▕ 

  • A class import is missing: You have a missing class import. Try importing this class: `Illuminate\Database\Seeder`. 

      +2 vendor frames 
  3   [internal]:0
      Composer\Autoload\ClassLoader::loadClass("Database\Seeders\PostCommentSeeder")

  4   [internal]:0
      spl_autoload_call("Database\Seeders\PostCommentSeeder")

PostCommentSeeder.phpのuseuse Illuminate\Database\Seeder;
書いてないからエラー出てたみたい。
useは外部からファイルを呼び出してパスを省略して書ける便利な所。

IlluminateはLaravelにデフォルトで備わってるクラスとメソッドが書いてある所。

ターミナル
$XXX bbc % php artisan db:seed --class=PostCommentSeeder

   Illuminate\Database\QueryException 

  SQLSTATE[HY000]: General error: 1364 Field 'comment_count' doesn't have a default value (SQL: insert into `posts` (`title`, `content`, `cat_id`, `updated_at`, `created_at`) values (1 番目の投稿, この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。, 1, 2024-08-01 05:51:27, 2024-08-01 05:51:27))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:712
    708▕         // If an exception occurs when attempting to run a query, we'll format the error
    709▕         // message to include the bindings with SQL, which will make this exception a
    710▕         // lot more helpful to the developer instead of just the database's errors.
    711▕         catch (Exception $e) {
  ➜ 712▕             throw new QueryException(
    713▕                 $query, $this->prepareBindings($bindings), $e
    714▕             );
    715▕         }
    716▕     }

      +12 vendor frames 
  13  database/seeders/PostCommentSeeder.php:19
      Illuminate\Database\Eloquent\Model::save()

      +22 vendor frames 
  36  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

Seederファイルというかマイグレーションファイルの方もミスってたらしい。

2024_07_05_093838_create_posts_table.php
$table->bigInteger('comment_count')->unsigned()->default('0');

しばらく四苦八苦してデフォルト値0を設定して修正完了。
php artisan migrate:freshを行う。
Seederファイルに戻ると、

ターミナル
miki@chatlune-air3 bbc % php artisan db:seed --class=PostCommentSeeder

   Error 

  Class 'Database\Seeders\Comment' not found

  at database/seeders/PostCommentSeeder.php:23
     19▕ 		$post->save();
     20▕ 
     21▕ 		$maxComments = mt_rand(3, 15);
     22▕ 		for ($j=0; $j <= $maxComments; $j++) {
  ➜  23▕ 			$comment = new Comment;
     24▕ 			$comment->commenter = '名無しさん';
     25▕ 			$comment->comment = $commentdammy;
     26▕ 
     27▕ 			// モデル(Post.php)のCommentsメソッドを読み込み、post_idにデータを保存する

      +22 vendor frames 
  23  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

また似たようなエラーが……。
モデルの方のファイルが最初スペルミスっていたのと、
namespaceuseを書いてない為と思われるエラーが次々出ました。

Comment.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

namespaceuseを記述。
Category.phpについても同じく記述しました。
ところで、VS Codeを使っているのですが、
namespaceを書いてる時に<?phpの前に改行を入れると赤くエラーが出ます。
しばらくそれでもつまづいたのですが、
エラーメッセージ的に「前になんか入れず、一番先に書けや」的なことなのかなと思います。

これでやっとSeederが動き出しました。

2024.8.2

Viewが表示されない

Seederは動いたものの、
投稿一覧の表示ページが表示されない!

スクリーンショット 2024-08-02 16.36.29.png

index.blade.phpがエラー吐いてる。

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>{{ $post->content }}</p>
	<p>{{ link_to("/bbc/ {$post->id} ", '続きを読む', array('class' => 'btn btn-primary') ) }}</p>
	<p>コメント数{{ $post->comment_count }}</p>
@endforeach

</div>

@stop

どうやらここがエラー吐いてるらしい。

index.blade.php エラー吐いてるところ
	<p>{{ link_to("/bbc/ {$post->id} ", '続きを読む', array('class' => 'btn btn-primary') ) }}</p>

そもそもlink_toというのはrailsの書き方らしい。
Laravel Collectiveというものがあり、
Laravel公式が削除した機能をフォローする非公式パッケージで、
そこで使えたようなLaravel 5.xとかの古の技術らしい。
(ということはこの個人ブログ相当前のバージョンで書かれてるんだな……)

スクリーンショット 2024-08-02 18.05.14.png

ということで無事投稿一覧ページが表示された。

2024.8.5

各投稿についてのページを表示させていく

今、投稿一覧ページの「続きを読む」ボタンをクリックしても、
Not Found
The requested URL was not found on this server.
が出てしまう。

URLが
http://localhost/bbc1
みたいになっているのに気づく→blade側のURL指定ミス?

index.blade.php
<a href="/bbc/{{$post->id}}"><button class="btn btn-primary">続きを読む</button></a>

/bbc/{{$post->id}}bbcの後ろに/が入ってなかったことによるミスだった。
URLは直ったけど、まだNot Found。

PostsController.php
    public function show($id)
    {
        $post = Post::find($id);
        Log::info("post",[$post]);
        return View::make('bbc.single')->with('post', $post);
    }

Logを仕込んでみると、Log取れてない……。
つまり、この関数が動いてないということ?

2024.8.6

続きを読むボタンが動かない

前回Logを取れていないことから、show($id)の関数が動いてないのではと推測。
bladeの続きを読むボタンのaタグで飛ばしているリンクが怪しいんじゃないか?

index.blade.php
<a href="{{ bbc/$post->id }}"><button class="btn btn-primary">続きを読む</button></a>

このページを参照して以下のようにコードを書き換えてみる。

index.blade.php
<a href="{{route('bbc.show',['id' => $post->id])}}"><button class="btn btn-primary">続きを読む</button></a>

そうするとindexページを開いた時にMissing required parameter for...のエラーが!

渡すパラメータの記述がうまく行っていない?
ここを参考に以下のように直す。

index.blade.php
<a href="{{route('bbc.show', $post->id)}}"><button class="btn btn-primary">続きを読む</button></a>

そうするとエラーがなくなり、「続きを読む」ボタンが動いた!

2024.8.8

投稿機能を作成する

以下のファイルを新規作成すると、新規投稿ページができるらしいが……

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' => 'bbc.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">電化製品</option>
				<option value="2" name="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() }}

</div>

@stop

問題1
ControllerにViewを表示させるメソッドを書いてないからこのままだとViewが表示されない
→Controllerに記述を足す

問題2
前問題になったLaravel Collectiveの書き方であるFormファザードが入ってるので動かない
→htmlのタグのformタグで書き直す

問題1

PostsController.php

    public function create()
    {
        return View::make('bbc.create');
    }

create関数に記述を書き足す。

問題2

formタグに書き直して、{{ csrf_field() }}のおまじないを添える

create.blade.php
<form action="{{route('bbc.create')}}" method="POST" class="form-horizontal">
  {{ csrf_field() }}

	<div class="form-group">
		<label for="title" class="">タイトル</label>
		<div class="">
            <input type="text" name="title">
		</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">電化製品</option>
				<option value="2" name="2">食品</option>
			</select>
		</div>
	</div>

	<div class="form-group">
		<label for="content" class="">本文</label>
		<div class="">
            <textarea rows="6" name="content"></textarea>
		</div>
	</div>

	<div class="form-group">
		<button type="submit" class="btn btn-primary">投稿する</button>
	</div>

</form>

これで新規投稿ページが表示された!

2024.8.8

投稿できない

次は投稿フォームのバリデーションとDBへの保存機能作りだが……。

PostsController.php
public function store()
{
	$rules = [
		'title' => 'required',
		'content'=>'required',
		'cat_id' => 'required',
	];

	$messages = array(
		'title.required' => 'タイトルを正しく入力してください。',
		'content.required' => '本文を正しく入力してください。',
		'cat_id.required' => 'カテゴリーを選択してください。',
	);

	$validator = Validator::make(Input::all(), $rules, $messages);

	if ($validator->passes()) {
		$post = new Post;
		$post->title = Input::get('title');
		$post->content = Input::get('content');
		$post->cat_id = Input::get('cat_id');
		$post->save();
		return Redirect::back()
			->with('message', '投稿が完了しました。');
	}else{
		return Redirect::back()
			->withErrors($validator)
			->withInput();
	}
}

上記を記述し、試しにバリデーションを機能させてみようと適当に投稿すると

スクリーンショット 2024-08-09 15.23.23.png

エラーが出る。
このエラーはFormタグのaction要素の遷移先が間違ってたりすると出るぽい

create.blade.php
<form action="{{route('bbc.create')}}" method="POST" class="form-horizontal">

このルーティングに問題があるようなのだが……。
まだどうしたらいいのかわからない。

2024.8.19

新規投稿をちゃんと動作させる

create.blade.php
<form action="{{route('bbc.create')}}" method="POST" class="form-horizontal">

ここのルーティングに問題がありそうなので、
PostsController.phpのstore関数の記述を一旦取って、

create.blade.php
<form action="{{route('bbc.store')}}" method="POST" class="form-horizontal">

にしたら、前回のエラーは出なくなった。

store関数の記述を戻すと、
またエラーが出る!

でもこのページを見るに、actionの遷移先はstoreで合っていそう?
次回もう一度調べる。

2024.8.20

バリデーションを動作させたい

どうもactionの遷移先はstoreで合っていそう。

  • create : 入力画面の生成とstoreへのデータの送信
  • store : 情報を受け取り保存(一覧へリダイレクト)

ビューでフォームに入力した情報を、storeメソッドで受け取る、
で認識が合ってそうなので、
create.blade.phpでフォームに入力するactionの遷移先はstoreだろう。
ということはstoreメソッドの中身が悪そう。

ValidatorファザードとRedirectorインスタンスについて
namespaceにuseの記述を足す。

PostsController.php
use Illuminate\Support\Facades\Validator;
use Illuminate\Routing\Redirector;

また、Validator::make()の第一引数の書き方が違うので訂正。
元々Input::all()となっていたけど、これも昔のLaravelのバージョンに
Inputファサードがあったっぽい。

ちなみにValidator::make()の引数についてはこちらを参考にした。

PostsController.php
$validator = Validator::make($request->all(), $rules, $messages);

更に、redirectについて、
return以降の書き方が違うみたいなので、書き直し。

PostsController.php
return back()->with('message', '投稿が完了しました。');
}else{
return back()->withErrors($validator)->withInput();
}

ここまで書き直したらバリデーションが上手くいった!

2024.8.22

特定のカテゴリーに属する記事一覧が表示できるようにする

まず、元記事のようにindex.blade.phpとPostsController.phpを編集する。

index.blade.php
<!-- <p>カテゴリー{{ $post->category->name }}</p> -->
<p>{{ link_to("/category/{$post->category->id}", $post->category->name, array('class' => '')) }}</p>
PostsController.php
public function showCategory($id)
{
	$category_posts = Post::where('cat_id', $id)->get();

	return View::make('category')
		->with('category_posts', $category_posts);
}

更にcategory.blade.phpを新規作成。

category.blade.php
@extends('layouts.default')
@section('content')

<div class="col-xs-8 col-xs-offset-2">

@foreach($category_posts as $category_post)

	<h2>タイトル{{ $category_post->title }}
		<small>投稿日{{ date("Y年 m月 d日",strtotime($category_post->created_at)) }}</small>
	</h2>

	<p>{{ $category_post->content }}</p>

	<p>{{ link_to("/bbc/{$category_post->id}", '続きを読む', array('class' => 'btn btn-primary')) }}</p>
	<p>コメント数{{ $category_post->comment_count }}</p>
	<hr />
@endforeach

</div>

@stop

以前の例でlink_toは古いLaravelの書き方なので、bladeを以下のように書き換え。

index.blade.php
<a href="/category/{{$post->category->id}}">{{$post->category->name}}</a>
category.blade.php
<a href="/bbc/{{$category_post->id}}"><button class="btn btn-primary">続きを読む</button></a>

これで
http://localhost/public/bbc
のカテゴリーのリンクを押下すると

スクリーンショット 2024-08-22 19.09.59.png

Not Foundになる。
showCategoryメソッド通ってない気がする。
Logを仕込んだら通っていない。

そもそも一覧ページにリンクするaタグの遷移先が違うのでは?と考えて、
href要素の中身を弄った。

index.blade.php
<a href="{{route('bbc.category', $post->category->id)}}">{{$post->category->name}}</a>

それに伴って、ルーティングも弄ってみた。

web.php
Route::get('bbc/category/{$id}',[PostsController::class, 'showCategory'])->name('bbc.category');

弄っているうちにエラーは出なくなったけど、まだ表示されない。
→ルーティングが間違っている?

{$id}の$を抜いたら動いた!
なんか抜く前はshowメソッドに行ってたっぽい

web.php
Route::get('bbc/category/{id}', [PostsController::class, 'showCategory'])->name('bbc.category');

2024.8.23

コメント投稿機能を作る

新しくコメント投稿機能を作る。
まず、ビューから。

single.blade.php

<h3>コメント一覧</h3>
@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

その後、コントローラーを新規作成

$ php artisan make:controller CommentsController

出来たコントローラーに以下を記述

CommentsController.php
public function store()
{
	$rules = [
		'commenter' => 'required',
		'comment'=>'required',
	];

	$messages = array(
		'commenter.required' => 'タイトルを正しく入力してください。',
		'comment.required' => '本文を正しく入力してください。',
	);

	$validator = Validator::make(Input::all(), $rules, $messages);

	if ($validator->passes()) {
		$comment = new Comment;
		$comment->commenter = Input::get('commenter');
		$comment->comment = Input::get('comment');
		$comment->post_id = Input::get('post_id');
		$comment->save();
		return Redirect::back()
			->with('message', '投稿が完了しました。');
	}else{
		return Redirect::back()
			->withErrors($validator)
			->withInput();
	}
}

ルーティングを記載。

web.php
Route::resource('comment', CommentsController::class);

single.blade.phpは、このままだとFormファザードの書き方で、エラーが出てしまうので、
以下のように書き換え。

single.blade.php
<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 action="{{route('comment.store')}}" method="POST" class="form">
  {{ csrf_field() }}

	<div class="form-group">
		<label for="commenter" class="">名前</label>
		<div class="">
			<input type="commenter" name="title">
		</div>
	</div>

	<div class="form-group">
		<label for="comment" class="">コメント</label>
		<div class="">
			<textarea rows="6" name="content"></textarea>
		</div>
	</div>

	<input type="hidden" name="post_id" value="{{$post->id}}">

	<div class="form-group">
		<button type="submit" class="btn btn-primary">投稿する</button>
	</div>

</form>


</div>

@stop

以上で、見かけはコメント投稿フォームが出来たが、
投稿するとエラーが出るのでまた次回対策する。

スクリーンショット 2024-08-23 18.43.22.png

2024.8.26

コメント投稿機能が動かない

まず、web.phpにコントローラーの記述を足す。

web.php
use App\Http\Controllers\CommentsController;

また、CommentsController.phpに各種useを足す。

CommentsController.php
use App\Models\Comment;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Routing\Redirector;

ここらへんで、エラーは出ないのに、バリデーションが働いてコメントが投稿されなくなる。
$requestのログをとると、なんか変。

laravel.log
[2024-08-26 09:01:06] local.INFO: request {"_token":"P7xnAf1P6CWDPh4ICSYI8rVhKpKDWNaZNUhFjIlu","title":"aaaa","content":"aaaa","post_id":"1"} 

コメントの$requestなのにtitleとcontentになってる。
single.blade.phpを修正。

single.blade.php
	<div class="form-group">
		<label for="commenter" class="">名前</label>
		<div class="">
			<input type="text" name="commenter">
		</div>
	</div>

	<div class="form-group">
		<label for="comment" class="">コメント</label>
		<div class="">
			<textarea rows="6" name="comment"></textarea>
		</div>
	</div>

そうすると、Input::がエラー吐いてきた。
→書き換える。

CommentsController.php
            $comment->commenter = $request->get('commenter');
            $comment->comment = $request->get('comment');
            $comment->post_id = $request->get('post_id');

これにて無事元ブログの指示する掲示板は完成!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0