2
0

More than 5 years have passed since last update.

コメント機能の実装でハマった話

Last updated at Posted at 2019-06-17

投稿文に対してコメントをつける機能を実装する

エラー文
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into comments (body, updated_at, created_at) values (あああああああああ, 2019-06-17 20:28:43, 2019-06-17 20:28:43))

検証①
user_idに値が設定されていないという文面。たぶんuser_idがうまくpostされてないのかな?と思った。
user_idとpost_idはcommentsテーブルの必須項目のカラム。
しかし、ブラウザでHTMLソースを見ても<input type="hidden" name="user_id" value="{{ $user->id }}">で値が入っている。

show.blade.php
@extends('layouts.app')

@section('title', 'レビューページ')

@section('content')
    <div class="container mt-4">
        <div class="border p-4">
            <h1 class="h5 mb-4">
                {{ $post->title }}
            </h1>
            <div class="user-name text-right">{{ $post->user->name }}さん</div>

            <p class="mb-5">
                {!! nl2br(e($post->body)) !!}
            </p>
            @if (Auth::check())
            <form class="mb-4" method="POST" action="/post/{{ $post->id }}">
                @csrf
                <input type="hidden" name="post_id"  value="{{ $post->id }}">
                <input type="hidden" name="user_id" value="{{ $user->id }}">

                <div class="form-group">
                    <label for="body">
                        本文
                    </label>

                    <textarea
                        id="body"
                        name="body"
                        class="form-control {{ $errors->has('body') ? 'is-invalid' : '' }}"
                        rows="4"
                    >{{ old('body') }}</textarea>
                    @if ($errors->has('body'))
                        <div class="invalid-feedback">
                            {{ $errors->first('body') }}
                        </div>
                    @endif
                </div>

                <div class="mt-4">
                    <button type="submit" class="btn btn-primary">
                        コメントする
                    </button>
                </div>
            </form>
            @endif
            <section>

検証②
(SQL: insert into comments (body, updated_at, created_at)...
SQL文にuser_idとpost_idのカラム指定がないぞ。なんで?コントローラ内の記述にミスがないか確認。
$params = $request->all();の中身にuser_idとpost_idが入ってないのかな?
エラーを吐き出している処理のComment::create($params);をコメントアウトして$paramsの中身を確認。
$paramsにはuser_idとpost_idを含めた正常な値が配列で表示された。

CommentController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;
use App\Comment;

class CommentController extends Controller
{
  public function store(Request $request)
  {
      $validate_rule = [
          'post_id' => 'required|exists:posts,id',
          'body' => 'required|max:2000',
      ];
      $this->validate($request, $validate_rule);
      $params = $request->all();
      return $params;
      //Comment::create($params);
      return redirect()->route('posts_show', ['id' => $request->post_id]);
  }
}

検証③
値もしっかり入っててpostされているのになんでDBに保存できないんだろうか?
Comment::create($params);の処理を作っているモデルの方を確認する。

Comment.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Post;
use App\User;

class Comment extends Model
{
    protected $fillable =['body'];

    public function post()
    {
      return $this->belongsTo('App\Post');
    }

    public function user()
    {
      return $this->belongsTo('App\User');
    }
}

あれ??protected $fillable =['body'];がbodyフィールドだけになっている...違和感を感じ

Comment.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Post;
use App\User;

class Comment extends Model
{
    protected $fillable =['body', 'post_id', 'user_id];

    public function post()
    {
      return $this->belongsTo('App\Post');
    }

    public function user()
    {
      return $this->belongsTo('App\User');
    }
}

protected $fillable =['body', 'post_id', 'user_id];に修正。
無事、コメント投稿された。とても時間がかかってしまった。。。

なぜこのエラーの解決にハマったのか(時間がかかったか)

  • 実行されたSQL文を勘違いしていた。値が取得できていないからuser_idとpost_idのカラム指定がないと思っていた。
  • $paramsの中身を確認する方法が最初わからなかった。
  • 勘や予測を頼りにデバッグしていた。

デバッグは勘や読みに頼りすぎず、観察することを優先する。原因を切り分け順序を追って一つ一つ潰していくこと。効率のよいデバッグ方法は順を追って観察すること。

今後の対策として実行

  • ログにSQLクエリを出力させて、普段から見るようにした。
2
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
2
0