ajaxを使って、サーバー側へ処理を送ろうとすると、500番のエラーが返ってきてなかなか解決できません。
ちなみに、Laravelで書いております。
日記投稿アプリのようなものを作っています。
現在、つまづいているところは、各投稿につけた「いいね」ボタンをajaxを使って処理するところです。
「いいね」ボタンをクリックすると、ajaxでクリックされた投稿の「いいね」ボタンが+1され、色がつくようにしたいです。
下が、jsファイルです。
js
1$(function(){ 2 3 // いいねボタンのクリック 4 $(document).on('click', '.js-like', function() { 5 let diaryId = $(this).siblings('.diary-id').val(); 6 let $clickedBtn = $(this); 7 // console.log(diaryId); 8 // console.log($clickedBtn); 9 10 // like 関数を実行 11 like(diaryId, $clickedBtn); 12 }); 13 14 // like 関数を作成 15 function like(diaryId, $clickedBtn) { 16 $.ajax({ 17 url: 'diary/' + diaryId + '/like', 18 type: 'POST', 19 dataType: 'json', 20 // LaravelではCSRF対策として、tokenを送信しないとエラーが発生します。 21 headers: { 22 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 23 }, 24 }) 25 .then( 26 function(data) { 27 changeLikeBtn($clickedBtn); 28 // いいねの数を1増やす 29 let num = Number($clickedBtn.siblings('.js-like-num').text()); 30 $clickedBtn.siblings('.js-like-num').text(num + 1); 31 }, 32 function() { 33 console.log('なんでやねん'); 34 console.log(error); 35 } 36 ) 37 } 38 39 40 41 // いいね, いいね解除でボタンの色を変更、 42 // js-like, js-dislikeでいいね, いいね解除の切り替えをしてるためクラスの付け替え 43 function changeLikeBtn(btn) { 44 btn.toggleClass('far').toggleClass('fas'); 45 btn.toggleClass('js-like').toggleClass('js-dislike'); 46 } 47})
下が、PHPファイル(index.blade.php)です。
php
1<!-- layout.blade.phpをテンプレとして使う --> 2@extends('layouts.app') 3 4<!-- layout.blade.phpのcontentの部分 --> 5@section('content') 6 <a href="{{ route('diary.create') }}" class="btn btn-primary btn-block">新規投稿</a> 7 8 <!-- コントローラーから送られたキーで値をとる・この場合、$diariesがキーである --> 9 @foreach($diaries as $diary) 10 <div class="m-4 p-4 border border-primary"> 11 <p>{{$diary->title}}</p> 12 <p>{{$diary->body}}</p> 13 <p>{{$diary->created_at}}</p> 14 15 <!-- ログインしている Auth::check() && ログインしているユーザーの投稿であれば Auth::user()->id === $diary->user_id --> 16 @if(Auth::check() && Auth::user()->id === $diary->user_id) <!-- ログインしているユーザーの投稿であれば --> 17 <a class="btn btn-success" href="{{ route('diary.edit', ['id' => $diary->id]) }}">編集</a> 18 19 <form action="{{ route('diary.destroy', ['id' => $diary->id]) }}" method="POST" class="d-inline"> 20 @csrf 21 @method('delete') 22 <button class="btn btn-danger">削除</button> 23 </form> 24 @endif 25 <div class="mt-3 ml-3"> 26 <i class="far fa-heart fa-lg text-danger js-like"></i> 27 <input class="diary-id" type="hidden" value="{{ $diary->id }}"> 28 <span class="js-like-num">200</span> 29 </div> 30 </div> 31 @endforeach 32@endsection
下は、web.phpです。ルートの記述をしています。
php
1 2// 一覧以外のページはログインしていないと表示(実行)できないように変更 ログインしていない場合リダイレクト 3Route::group(['middleware' => 'auth'], function() { 4 Route::get('diary/create', 'DiaryController@create')->name('diary.create'); 5 Route::post('diary/create', 'DiaryController@store')->name('diary.create'); 6 7 Route::get('diary/{diary}/edit', 'DiaryController@edit')->name('diary.edit'); 8 Route::put('diary/{diary}/update', 'DiaryController@update')->name('diary.update'); 9 10 Route::delete('diary/{diary}/delete', 'DiaryController@destroy')->name('diary.destroy'); 11 12 Route::post('diary/{id}/like', 'DiaryController@like'); 13 Route::post('diary/{id}/dislike', 'DiaryController@dislike'); 14}); 15 16Auth::routes();
下が、DiaryController.phpでコントローラーファイルです。エラー原因要因の箇所は、下のlikeメソッドです。
php
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use App\Diary; // App は Diary.php の namespace App; からきている 7use App\Http\Requests\CreateDiary; // 認証ルールを作ったRequestファイルを読み込む 8 9class DiaryController extends Controller 10{ 11 // プロパティ 12 13 // メソッド 14 15 // 一覧表示するメソッド 16 public function index() 17 { 18 // diariesテーブルのデータを全件取得 19 // allメソッド : 全件データを取得するメソッド Modelクラスの中に入っているから使える。extendsしている 20 $diaries = Diary::all(); // Diary だから、 diariesのテーブルにアクセス(この場合allメソッドを)する 21 22 // dd($diaries); // var_dump + 処理をここで中断 23 24 // view('フォルダ名.ファイル名(blade.phpは除く), [配列など渡してあげたいもの]'); 25 return view('diaries.index', [ 26 // キー と 値で渡す (別ファイルで、キーは、$diariesで指定) 27 'diaries' => $diaries 28 ]); 29 } 30 31 // 新規追加の画面を表示するメソッド 32 public function create() 33 { 34 return view('diaries.create'); 35 } 36 37 // 新規追加の場面で投稿ボタンが押されたとき 38 // 投稿処理をするメソッド 39 // 引数のRequest = $_POST みたいなイメージ 40 public function store(CreateDiary $request) 41 { 42 // ここからデータの登録・・・投稿されたデータをdiariesテーブルに入れたい 43 // Diaryモデルのインスタンスを取得 44 $diary = new Diary(); 45 46 // 画面で入力されたタイトルを代入 47 // 画面で渡ってきたtitle($requestに入っている)を、設定 48 $diary->title = $request->title; 49 // 画面で入力された本文を代入 50 $diary->body = $request->body; 51 $diary->user_id = \Auth::user()->id; //追加 ログインしてるユーザーのidを保存 \Auth::user() = ログインしているユーザー 52 53 // モデルからデータベースにデータを追加するとき save() = INSERT INTO 54 $diary->save(); // DBに保存 55 56 // 一覧ページにリダイレクト (これやらないと、戻るボタン押したとき[二重登録される]) [フォームを再送信しますか?]のアラートが出なくなる 57 // 戻ったときのフォームを再送信しますか?の対策のため 58 return redirect()->route('diary.index'); 59 } 60 61 // 削除を実行するメソッド 62 public function destroy(Diary $diary) // バインディングした 63 { 64 // URLを直接入力しても表示できないようにする ログインしているユーザー != 投稿のユーザーIDと一致していなければ、 65 if (\Auth::user()->id !== $diary->user_id) { 66 abort(403); 67 } 68 69 // Diaryモデルのインスタンス化 しなくてもいけるべや 70 // $diaries = new Diary(); 71 72 // Diaryモデルを使って、削除したい要素の取得 73 // $diary = $diaries->find($id); 74 // $diary = Diary::find($id); 75 76 // 取得した要素を削除 77 $diary->delete(); 78 79 // 一覧画面に戻る 80 return redirect()->route('diary.index'); 81 82 } 83 84 // 編集画面を表示するメソッド 85 // public function edit(int $id) 86 public function edit(Diary $diary) // $diary = Diary::find($id); 自動的に該当するモデルのインスタンスを作成 87 { 88 89 // URLを直接入力しても表示できないようにする ログインしているユーザー != 投稿のユーザーIDと一致していなければ、 90 if (\Auth::user()->id !== $diary->user_id) { 91 abort(403); 92 } 93 94 95 // この仕組みを、ルートモデルバインディング [バインド=縛られる・対応] 96 97 // IDをもとに1件取得 バインディングしたからいらない 98 // $diary = Diary::find($id); 99 100 // 編集画面を表示するとき、取得結果を渡す 101 return view('diaries.edit', [ 102 'diary' => $diary 103 ]); 104 } 105 106 // 編集処理をするメソッド 107 public function update(CreateDiary $request, Diary $diary) // バインディングした 108 { 109 110 // URLを直接入力しても表示できないようにする ログインしているユーザー != 投稿のユーザーIDと一致していなければ、 111 if (\Auth::user()->id !== $diary->user_id) { 112 abort(403); 113 } 114 115 // IDをもとに、投稿のタイトル、本文を更新 インスタンス化しなくても使えるということは、static function find () 116 // $diary = Diary::find($id); 117 118 $diary->title = $request->title; 119 $diary->body = $request->body; 120 121 $diary->save(); // updateしているからデータベースで自動で、更新の日時が入る migrationファイルにtimestampがある 122 // 一覧ページにリダイレクト 123 return redirect()->route('diary.index'); 124 } 125 126 // いいねの数 127 public function like(int $id) 128 { 129 $diary = Diary::where('id', $id)->with('likes')->first(); 130 // Diaryモデルのlikesメソッド 131 $diary->likes()->attach(Auth::user()->id); 132 } 133 134}
下は、Diary.phpでモデルファイルです。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Diary extends Model { // リレーションを定義 linksテーブルを中間テーブルとした、多対多の関係 public function likes() { return $this->belongsToMany('App\User', 'likes')->withTimestamps(); } }
これまでにやってことは、TOKENの確認、データ(id)の受け渡しの確認。
該当箇所
app.js:1 POST http://127.0.0.1:8001/diary/8/like 500 (Internal Server Error)