Laravelでajax通信をする
写真に添えられたチェックボックスをクリックすることでタグ付けができるアプリを作りました。
元々はLaravelでformをPOSTしていましたが、ajax通信にすることでページ遷移せずにformをPOSTできるようにしたかった。その作業メモです。
1.まずはLaravelにjQueryをインストールする。
1-1. jQueryをインストールする。Laravelのプロジェクトディレクトリにて下記実行。
$ npm install jquery --save
1-2.resources/js/ディレクトリに、適当な.jsファイルを作って中に記述する。
※今回はajaxPost.jsを作った
とりあえずちゃんと動作するか確認するために下記のコードを記述
$(function(){
console.log('run jQuery')
});
1-3.webpack.mix.jsを編集する
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/ajaxPost.js', 'public/js') //追加。作成したajaxPost.jsファイルを、public/jsディレクトリにつなげる。
.autoload( {"jquery": [ '$', 'window.jQuery' ],} ) //追加。jQueryを使えるようにするため
.vue()
.sass('resources/sass/app.scss', 'public/css');
1-4.ビルドする
$ npm run dev
public/jsディレクトリにajaxPost.jsが表示される
1-5.ちゃんと動くかテストする
作ったjsファイルを読み込みたいBladeファイルにソースを貼る
<script src="{{mix('js/ajaxPost.js')}}"></script>
このBladeファイルを開いたときにコンソールに'run jQuery'
と表示されていればちゃんと読み込みできてます。
ここまで出来てれば、LaravelでjQueryが使えるようになったぜ。
2.ajax通信
元々のコード
マイグレーションファイル
create_photos_table.php
public function up()
{
Schema::create('photos', function (Blueprint $table) {
$table->id();
$table->string('path');//追記!!!
$table->dateTime('date')->nullable();//追記
$table->timestamps();
});
}
create_players_table.php
public function up()
{
Schema::create('players', function (Blueprint $table) {
$table->id();
$table->string('name_kanji');//追記
$table->string('name_kana');//追記
$table->string('nickname');//追記
$table->integer('number');//追記
$table->timestamps();
});
}
中間テーブル
create_photo_player_table.php
public function up()
{
Schema::create('photo_player', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('photo_id');
$table->unsignedBigInteger('player_id');
$table->foreign('photo_id')->references('id')->on('photos')->onDelete('cascade');
$table->foreign('player_id')->references('id')->on('players')->onDelete('cascade');
$table->timestamps();
});
}
モデル
Photo.php
public function Players()
{
return $this->belongsToMany('App\Models\Player')->withTimestamps();
}
Player.php
public function Photos()
{
return $this->belongsToMany('App\Models\Photo')->withTimestamps();
}
ビューファイル
taggingAll.blade.php
<form class=form id="form" action="{{ route('photo.update',$photo->id)}}" method="POST">
@csrf
@method('PUT')
<p>
@foreach ($players->sortBy('number') as $player)
<label class="checkbox">
<input class="PlayerCheckBox" type="checkbox" name="players[]" value="{{$player->id}}"
@if(in_array($player->id , $photo->players->pluck('id')->toArray())) checked @endif>
<!-- player_idとphotoが持っているplayer_idが一致したらチェック -->
{{ $player->number }}{{ $player->nickname }}
</label>
@endforeach
</p>
</form>
コントローラー
PhotoController.php
public function update(Request $request, $id)
{
$photo = Photo::find($id);
$photo->players()->sync(request()->players);
return back()->with('success', '編集完了しました');
}
jsファイルの記述(ajax通信)
ajaxPost.js
$( function (){
$('.PlayerCheckBox').on('change', function(){ //checkboxをクリックした時に発動
// let form = $('#form') //これだと常に最初のformを指定してしまうのでだめ
let form = $(this.form); //クリックしたcheckboxを含むformをjqueryで取得
$.ajax({
headers: {
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
},
url : form.attr('action'), //formのaction要素を参照
type : form.attr('method'), //formのmethod要素を参照
data : form.serialize(), //formで送信している内容を送る
})
//通信が成功した時
.done((res)=>{
//何か処理
})
//通信が失敗したとき
.fail((error)=>{
//何か処理
})
})
});
↑のコードを書いた上でビルドする
$ npm run dev
public/js/ajaxPost.jsの内容が更新されていればビルドできている証拠
ビューファイルでの読み込み
taggingAll.blade.php
<script src="{{asset('js/ajaxPost.js')}}"></script>
もしくは
<script src="{{mix('js/ajaxPost.js')}}"></script>
これを忘れているとせっかく書いたajax通信の記述が使われないのでお忘れなく。