0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactとLaravel連携してデータ削除するまでの流れ

Last updated at Posted at 2025-01-14

つくったサンプル

Githubリポジトリ

一覧画面で削除対象のイベント(赤枠)を選択します。
削除1.png

選削除ボタンを押下します
削除2.png

正常に削除が完了すると。自動的に一覧画面に遷移します
削除3.png

データベースを見ても、対象のデータが削除されていますね。
削除4.png

ディレクトリ構造

ディレクトリ構造は、下記のようにしました。

ReactLaravelProject
├─ backend
│  ├─ app
│  │  ├─ Http
│  │  │  └─ Controllers
│  │  │     ├─ EventController.php
│  │  │     └─ RegisterController.php
│  │  └─ Models
│  │     └─ Event.php
│  └─ Routes
│     └─ api.php
└─ frontend
      └─ src
         ├─ components
         │  ├─ card
         │  │  └─ page.tsx
         │  └─ navbar
         │     └─ page.tsx
         ├─ dashboard  
         │     └─ page.tsx
         ├─ event
         │     ├─ eventDelete
         │     │  └─ page.tsx
         │     ├─ eventEdition
         │     │  └─ page.tsx
         │     └─ eventRegistration
         │        └─ page.tsx
         ├─ App.css
         ├─ App.tsx
         ├─ index.css
         ├─ index.tsx
         ├─ main.tsx
         └─ Tailwind.Config.js

フロント(React)側の削除画面を作る

axios.post で targetId を JSON ボディとして送る場合、targetId の値を JSON オブジェクトの一部として送るようにしましょう。

/frontend/src/event/eventDelete/page.tsx
await axios.post('http://localhost:8000/api/eventDelete',{eventId:targetId});
/frontend/src/event/eventDelete/page.tsx
import axios from "axios";
import { useNavigate,useSearchParams } from "react-router-dom"

export default function DeleteEvent(){
    //ルーティング設定する
    const navigate = useNavigate();

    //削除するボタンクリック時の処理
    const deleteEvent = async(e:React.FormEvent)=>{
        e.preventDefault();
        //alert("策k叙しますが、よろしいですか?");
        const response = await axios.post('http://localhost:8000/api/eventDelete',{eventId:targetId});
        if(response.request.status === 200){
            
            navigate('/dashboard');
        }else{
            alert("削除に失敗しました。");
        }
    }

    //戻るボタンクリックしたときの処理
    const backToDashboard = ()=>{
        navigate("/dashboard");
    }

    //URLクエリからデータを取得する
    const [searchParams] = useSearchParams();
    const targetId = searchParams.get('id');
    const targetName = searchParams.get('name');
    const targetDescription = searchParams.get('description'); 

    return (
        <div className="shadow-md border border-gray-500 rounded-md">
            <h2>削除ページ</h2>
            <div className="border border-gray-500">
                <div className="mb-4">
                    <label className="w-full font-bold text-2xl">
                        イベント名
                    </label>
                    <label className="w-full font-bold text-2xl">
                        {targetName}
                    </label>
                </div>
                <div>
                    <label className="w-full font-bold text-2xl">
                        イベント詳細
                    </label>
                    <label>
                        {targetDescription}
                    </label>
                </div>
            </div>
            <form onSubmit={deleteEvent}>
                <input type="hidden" name="eventId" defaultValue={targetId || null}/>
                <div className="flex items-center justify-center mt-8 mb-8">
                    <button className="bg-rose-500 text-white font-bold px-4 py-4 rounded-md mr-4">
                        削除する
                    </button>
                    <button type="button" className="bg-blue-500 text-white font-bold px-4 py-4 rounded-md" onClick={backToDashboard}>
                        戻る
                    </button>
                </div>
            </form>
        </div>
    )
}

サーバ(Laravel)側のコード

つづいてLaravel側です。

ルーティング設定

backend/Routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\RegisterController;//2025.01.08追加
use App\Http\Controllers\EventController;//2025.01.10追加

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post('/login',[RegisterController::class,'login']);//2025.01.08追加
Route::post('/eventRegistration',[EventController::class, 'registerEvent']);//2025.01.10追加
Route::post('/eventEdition',[EventController::class, 'editEvent']);
Route::get('/eventAllRead',[EventController::class, 'readAllEvents']);
Route::post('/eventDelete',[EventController::class, 'deletEvent']);

さいごに、削除する処理を追加します↓

backend/app/Http/Controllers/EventController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;//20250110追加
use App\Models\Event;//2025.01.10追加

class EventController extends Controller
{
    public function registerEvent(Request $request)
    {
        \Log::info('リクエストデータ:', $request->all());
        $request->validate([
            'eventName' => 'required|string|max:255',
            'eventDescription' => 'required|string|max:1000',
            'eventThumbnail' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
        ]);

        //元のファイル名を取得する
        $originalFileName = $request->file('eventThumbnail')->getClientOriginalName();
        //ファイル名が重複しないようにタイムスタンプを追加する。
        $fileName = time().'_'.$originalFileName;

        //カスタムファイル名で画像を保存する
        $imagePath = $request->file('eventThumbnail')->storeAs('public/event_thumbnails',$fileName);
        //公開URLを生成する
        $imageUrl = Storage::url($imagePath);

        //データベースに保存する
        $event = new Event();
        $event->name = $request->eventName;
        $event->description = $request->eventDescription;
        $event->thumbnail_path = $imageUrl;
        $event->save();

        return response()->json([
            'eventName' => $event->name,
            'eventDescription' => $event->description,
            'eventThumbnail' => $imageUrl,   
        ],200);
    }

    public function editEvent(Request $request){
        \Log::info('リクエストデータ:', $request->all());
        /*これは削除しておく
        $request->validate([
            'eventId' => 'required|integer',
            'eventName' => 'required|string|max:255',
            'eventDescription' => 'required|string|max:1000',
            'eventThumbnail' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // 画像は必須ではない場合
        ]);
                
        if ($validator->fails()) {
            return response()->json([
                'errors' => $validator->errors()
            ], 422);
        }
        */


        $targetId = $request->get('eventId');//$request->get('eventId')

        //画像ファイル処理
        $imageUrl = null;
        //$imageUrl = $request->file('eventThumbnail')->getClientOriginalName();
        
        if($request->hasFile('eventThumbnail')){
            
            //古い画像の削除
            if($imageUrl){
                // Storage::delete()で古い画像ファイルを削除
                $imagePath = public_path('storage') . '/' . basename($imageUrl); // 正しいパスに修正
                if (file_exists($imagePath)) {
                    unlink($imagePath);  // ファイル削除
                }
            }
            
            //元のファイル名を取得する
            $originalFileName = $request->file('eventThumbnail')->getClientOriginalName();
            //ファイル名が重複しないようにタイムスタンプを追加する。
            $fileName = time().'_'.$originalFileName;
            //カスタムファイル名で画像を保存する
            $imagePath = $request->file('eventThumbnail')->storeAs('public/event_thumbnails',$fileName);
            //公開URLを生成する
            $imageUrl = Storage::url($imagePath);

        }      

        //データベースの更新
        $event = Event::find($targetId);
        if (!$event) {
            return response()->json([
                'error' => 'イベントが見つかりません'
            ], 404);
        }

        $event->name = $request->eventName;
        $event->description = $request->eventDescription;
        $event->thumbnail_path = $imageUrl;
        if($imageUrl){
            $event->thumbnail_path = $imageUrl;
        }

        $event->save();
               
        return response()->json([
            'eventName' => $event->name,
            'eventDescription' => $event->description,
            'eventThumbnail' => $event->thumbnail_path,   
        ],200);
    }

    public function readAllEvents()
    {
        $events = Event::orderBy('id','asc')->get(); // findAll()ではなくall()を使用
        return response()->json($events, 200)
                ->header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
                ->header('Pragma', 'no-cache')
                ->header('Expires', 'Thu, 01 Jan 1970 00:00:00 GMT');
        /*
        return response()->json([
            $event
        ],200);
        */
    }

    public function deletEvent(Request $request)
    {
        $targetId = $request->get('eventId');
        //データの更新
        $event = Event::find($targetId);
        if(!$event){
            return response()->json(
                [
                    'error'=>'イベントが見つかりません'
                ]
            ,404);
        }

        $event->where('id',$targetId)->delete();
        return response()->json(
            [
                'message'=>'削除完了'
            ],200);
    }

}


以上です。

関連記事はこちら↓

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?