前提・実現したいこと
Laravelで販売管理システムを作成しているのですが、削除機能を実装したところ削除したいものとは別のものが削除されてしまいます。
実装当初は正常に機能していたのですが、リレーションを組んだ後から正常に削除できなくなりました。
エラーが出るわけではないので、調べようにもどのように調べたらいいか分からず行き詰ってます。
該当のソースコード
ProductModel
1class Product extends Model 2{ 3 //テーブル名 4 protected $table = 'products'; 5 6 // 可変項目 7 protected $fillable = 8 [ 9 'company_id', 10 'product_name', 11 'price', 12 'stock', 13 'comment', 14 'image', 15 ]; 16 17 // Companiesテーブルと関連付ける 18 public function company(){ 19 return $this->belongsTo('App\Models\Company'); 20 } 21}
CompanyModel
1class Company extends Model 2{ 3 //テーブル名 4 protected $table = 'companies'; 5 6 // 可変項目 7 protected $fillable = 8 [ 9 'company_name', 10 'street_address' 11 ]; 12 13 // protected $primaryKey = "company_id"; 14 15 // Productsテーブルと関連付ける 16 public function products(){ 17 return $this->hasMany('App\Models\Product'); 18 } 19}
controller
1/** 2 * 商品を削除する 3 * @param int $id 4 * @return view 5 */ 6 public function exeDelete($id) 7 { 8 if (empty($id)) { 9 \Session::flash('err_msg', 'データがありません。'); 10 return redirect(route('products')); 11 } 12 13 try { 14 // 商品を削除 15 Product::destroy($id); 16 } catch(\Throwable $e) { 17 abort(500); 18 } 19 20 \Session::flash('err_msg', '商品を削除しました。'); 21 return redirect(route('products')); 22 }
Route
1// 商品削除 2Route::post('/product/delete/{id}', 'ProductController@exeDelete')->name('delete');
ListBlade
1@extends('product.layout') 2@section('title', '商品一覧') 3@section('content') 4<div class="row"> 5 <div class="input-group"> 6 <form class="form-inline" action="{{ route('search') }}" method="get"> 7 <input name="search" value="" type="text" class="form-control input-lg" placeholder="商品名"> 8 9 <select class="form-control" name="search"> 10 <option selected disabled>メーカー名</option> 11 @foreach($products as $product) 12 <option id="company_id" name="company_id" value="{{ $product->id }}">{{ $product->company_name }}</option> 13 @endforeach 14 </select> 15 16 <button type="submit" class="btn btn-primary">検索</button> 17 </form> 18 </div> 19 20 <div class="mb-5 col-md-10 col-md-offset-2"> 21 <h2 class="text-secondary mt-3">商品一覧</h2> 22 23 @isset($search_result) 24 <p class="text-danger">{{ $search_result }}</p> 25 @endisset 26 27 @if (session('err_msg')) 28 <p class="text-danger">{{ session('err_msg') }}</p> 29 @endif 30 31 <table class="table table-striped text-secondary"> 32 <tr> 33 <th>ID</th> 34 <th>商品画像</th> 35 <th>商品名</th> 36 <th>価格</th> 37 <th>在庫数</th> 38 <th>メーカー名</th> 39 <th></th> 40 <th></th> 41 </tr> 42 @foreach($products as $product) 43 <tr> 44 <td>{{ $product->id }}</td> 45 <td><img src="{{ asset('/storage/' . $product->image) }}" class="img-fluid" alt="{{ $product->image }}" width="200" height="200"></td> 46 <td>{{ $product->product_name }}</td> 47 <td>{{ $product->price }}</td> 48 <td>{{ $product->stock }}</td> 49 <td>{{ $product->company_name }}</td> 50 <td><button type="button" class="btn btn-primary" onclick="location.href='/product/detail/{{ $product->id }}'">詳細</button></td> 51 52 <form method="POST" action="{{ route('delete', $product->id) }}" onSubmit="return checkDelete()"> 53 @csrf 54 <td><button type="submit" class="btn btn-secondary" onclick=>削除</button></td> 55 </form> 56 </tr> 57 @endforeach 58 </table> 59 </div> 60</div> 61<script> 62function checkDelete(){ 63if(window.confirm('削除してよろしいですか?')){ 64 return true; 65} else { 66 return false; 67} 68} 69</script> 70@endsection
補足情報(FW/ツールのバージョンなど)
Laravel5.8
MAMP
Windows
どういう定義のテーブル・モデルにどいうデータがあってどう削除されるのでしょう。
あと本件とは関係ないですがWindowsにMAMPは悪手です。
ProductモデルとCompanyモデルを記載してますが、これでは情報不足でしょうか?
会社の課題なのですが、指定がMAMPで所持しているのがWindowsのみなので。。
FOREIGN KEY制約(外部キー制約)を設定したのですか?
コードを見ていただければ分かる通り、1対多で外部キー制約を設定しています。
companiesテーブルのidを主キーにproductsテーブルのcompany_idを外部キーにしています。
テーブルの中身はそれぞれのモデルに記述してある通りです。
>会社の課題なのですが、
でしたら先輩や上司、出題者に聞いたほうが良いでしょうね。
できるだけ自力での制作を求められているので、こうしてWeb上で質問させて頂いてます。
リレーションはあってますか確認して見て見ましょう
dd($product->company);
dd($company->products);
SQLも確認しましょう
\DB::enableQueryLog();
Product::destroy($id);
dd(\DB::getQueryLog());
でSQLが表示されます。
リレーションの確認はどの部分に入れて確認したらよいのでしょうか?
正直なところLaravel歴1か月も満たない超初心者のため、まだまだ分からないことだらけです。。
\DB::enableQueryLog();
Product::destroy($id);
dd(\DB::getQueryLog());
で確認したところ、419エラーとなりました。
調べたところ@csrfが原因とのことでしたので、bladeを確認したところ、formの閉じタグが抜けていました。
中身はこのようになっていました。
array:2 [▼
0 => array:3 [▼
"query" => "select * from `products` where `id` in (?)"
"bindings" => array:1 [▼
0 => "7"
]
"time" => 5.43
]
1 => array:3 [▼
"query" => "delete from `products` where `id` = ?"
"bindings" => array:1 [▼
0 => 7
]
"time" => 278.95
]
]
見た感じid=7のproductしか削除してません。
> 削除したいものとは別のものが削除されてしまいます。
とは何が削除されたのでしょうか?
オブザーバーは定義してますか?
例えば、id10を削除しているのに実際に削除されるのはid1みたいなことが起こります。
見た感じ登録した順に削除されているようです。
なので、引数で渡している$idが上手く機能していないように思えます。
オブザーバーは定義していないです。
bladeもアップさせて頂けますか?
blade追加いたしました。
何か所か変更した箇所があるので、もしかしたら現状正常に削除ができるのかもしれないですが、また違う箇所が削除されるのが怖くて削除を試せないです。。
テストデータなので消えても問題はないのですが。。
ちなみにddで確認したところ、引数で渡している$idには正常にテーブルのidが渡されていました。
見た感じ問題はありません
今確認したところ、正常に削除できました!
もしかしたら最初からformの閉じタグがないことが原因だったのかもしれません。。
いろいろと見ていただきありがとうございましたm(_ _)m
あなたの回答
tips
プレビュー