You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中使用AJAX实现无刷新更新Session的问题求助

问题描述

正在开发购物车系统,需要实现点击Add按钮时为指定assignment创建Session并在页面展示,暂未实现增减数量、删除逻辑。目前无法做到不刷新页面就存储Session并更新页面内容,操作后页面会强制刷新,求解决方案。

现有代码

Controller代码

public function storeAssignmentSession($id, Request $request) {
    $assignmentId = $request->input('assignment_id');
    $quantity = 1; // Default quantity is 1
    $assignment = Assignment::find($assignmentId);

    if ($assignment) {
        $taskSession = session('session_' . $id, []);

        $existingKey = null;
        foreach ($taskSession as $key => $sessionData) {
            if ($sessionData['assignment_id'] === $assignment->id) {
                $existingKey = $key;
                break;
            }
        }

        if ($existingKey !== null) {
            $taskSession[$existingKey]['quantity'] += $quantity;
        } else {
            $taskSession[] = [
                'assignment_id' => $assignment->id,
                'assignment_name' => $assignment->assignment_name,
                'assignment_status' => $assignment->assignment_status,
                'quantity' => $quantity,
            ];
        }

        session(['session_' . $id => $taskSession]);
    }

    return redirect()->back();
}

Route代码

Route::post('/task/{id}/store-assignment-session', [Taskmanager::class, 'storeAssignmentSession'])->name('store_assignment_session');

Blade代码

<script>
$(document).ready(function() {
    // Handle the "Add" button click
    $(".add-assignment").click(function(e) {
        e.preventDefault(); // Prevent the default form submission
        
        var assignmentId = $(this).data("assignment-id");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/store-assignment-session',
            data: { assignment_id: assignmentId },
            success: function(response) {
                // Load the page to refresh the content
                location.reload();

                // Log the session data in the console
                console.log(response);
            },
            error: function(error) {
                alert('Failed to add assignment to session.');
            }
        });
    });
    
    // Handle the "Subtract" button click
    $(".subtract-assignment").click(function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/subtracting-assignment-session/' + key,
            success: function(response) {
                // Load the page to refresh the content
                location.reload();
            },
            error: function(error) {
                alert('Failed to subtract assignment from session.');
            }
        });
    });
    
    // Handle the "Add" button click
    $(".add-assignment").click(function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/adding-assignment-session/' + key,
            success: function(response) {
                // Load the page to refresh the content
                location.reload();
            },
            error: function(error) {
                alert('Failed to add assignment to session.');
            }
        });
    });
    
    // Handle the "Delete" button click
    $(".delete-assignment").click(function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/delete-assignment-session/' + key,
            success: function(response) {
                // Load the page to refresh the content
                location.reload();
            },
            error: function(error) {
                alert('Failed to delete assignment from session.');
            }
        });
    });
});
</script>
解决方案

核心思路:后端返回JSON格式的购物车数据,前端通过AJAX接收后直接修改页面DOM,替代页面刷新;同时修复原有代码中的重复事件绑定、CSRF令牌缺失问题。

1. 修改Controller返回JSON数据

将跳转响应改为返回包含购物车数据的JSON,让前端直接拿到最新购物车状态:

public function storeAssignmentSession($id, Request $request) {
    $assignmentId = $request->input('assignment_id');
    $quantity = 1; // Default quantity is 1
    $assignment = Assignment::find($assignmentId);

    if ($assignment) {
        $taskSession = session('session_' . $id, []);

        $existingKey = null;
        foreach ($taskSession as $key => $sessionData) {
            if ($sessionData['assignment_id'] === $assignment->id) {
                $existingKey = $key;
                break;
            }
        }

        if ($existingKey !== null) {
            $taskSession[$existingKey]['quantity'] += $quantity;
        } else {
            $taskSession[] = [
                'assignment_id' => $assignment->id,
                'assignment_name' => $assignment->assignment_name,
                'assignment_status' => $assignment->assignment_status,
                'quantity' => $quantity,
            ];
        }

        session(['session_' . $id => $taskSession]);
    }

    // 返回JSON格式的操作结果和购物车数据
    return response()->json([
        'success' => true,
        'cart' => session('session_' . $id)
    ]);
}

后续实现增减数量、删除的Controller方法时,也需返回相同格式的JSON数据。

2. 修复Blade中的AJAX逻辑

2.1 确保CSRF令牌验证

Laravel默认拦截无CSRF令牌的POST请求,在页面头部添加CSRF meta标签:

<meta name="csrf-token" content="{{ csrf_token() }}">

2.2 修改JS代码,移除页面刷新,动态更新DOM

修复重复的add-assignment事件绑定,添加DOM更新函数,移除location.reload():

$(document).ready(function() {
    // 全局配置AJAX携带CSRF令牌
    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    });

    // 处理Add按钮点击(仅保留一个绑定)
    $(".add-assignment").click(function(e) {
        e.preventDefault();
        
        var assignmentId = $(this).data("assignment-id");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/store-assignment-session',
            data: { assignment_id: assignmentId },
            success: function(response) {
                if (response.success) {
                    updateCartDisplay(response.cart);
                    console.log('商品已添加到购物车');
                }
            },
            error: function(error) {
                alert('Failed to add assignment to session.');
            }
        });
    });

    // 处理数量减少按钮点击
    $(".subtract-assignment").click(function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/subtracting-assignment-session/' + key,
            success: function(response) {
                if (response.success) {
                    updateCartDisplay(response.cart);
                }
            },
            error: function(error) {
                alert('Failed to subtract assignment from session.');
            }
        });
    });

    // 处理数量增加按钮点击(修改类名避免和添加按钮冲突)
    $(document).on('click', '.add-quantity-assignment', function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/adding-assignment-session/' + key,
            success: function(response) {
                if (response.success) {
                    updateCartDisplay(response.cart);
                }
            },
            error: function(error) {
                alert('Failed to add assignment quantity.');
            }
        });
    });

    // 处理删除按钮点击
    $(".delete-assignment").click(function() {
        var key = $(this).data("key");
        var taskId = {{$task->id}};
        
        $.ajax({
            type: 'POST',
            url: '/task/' + taskId + '/delete-assignment-session/' + key,
            success: function(response) {
                if (response.success) {
                    updateCartDisplay(response.cart);
                }
            },
            error: function(error) {
                alert('Failed to delete assignment from session.');
            }
        });
    });

    // 动态更新购物车展示的函数
    function updateCartDisplay(cartData) {
        var cartContainer = $('#cart-container');
        cartContainer.empty();

        if (cartData.length === 0) {
            cartContainer.html('<p>购物车为空</p>');
            return;
        }

        // 循环生成购物车项HTML
        cartData.forEach(function(item, index) {
            var cartItem = `
                <div class="cart-item">
                    <h4>${item.assignment_name}</h4>
                    <p>状态: ${item.assignment_status}</p>
                    <p>数量: ${item.quantity}</p>
                    <button class="subtract-assignment" data-key="${index}">-</button>
                    <button class="add-quantity-assignment" data-key="${index}">+</button>
                    <button class="delete-assignment" data-key="${index}">删除</button>
                </div>
            `;
            cartContainer.append(cartItem);
        });
    }
});

2.3 添加购物车展示容器

在Blade页面中添加用于展示购物车的容器,初始内容从Session读取:

<div id="cart-container">
    @if(session('session_' . $task->id))
        @foreach(session('session_' . $task->id) as $key => $item)
            <div class="cart-item">
                <h4>{{ $item['assignment_name'] }}</h4>
                <p>状态: {{ $item['assignment_status'] }}</p>
                <p>数量: {{ $item['quantity'] }}</p>
                <button class="subtract-assignment" data-key="{{ $key }}">-</button>
                <button class="add-quantity-assignment" data-key="{{ $key }}">+</button>
                <button class="delete-assignment" data-key="{{ $key }}">删除</button>
            </div>
        @endforeach
    @else
        <p>购物车为空</p>
    @endif
</div>

3. 示例:数量增加的Controller和Route

Controller方法

public function addAssignmentQuantity($id, $key) {
    $taskSession = session('session_' . $id, []);
    
    if (isset($taskSession[$key])) {
        $taskSession[$key]['quantity'] += 1;
        session(['session_' . $id => $taskSession]);
    }
    
    return response()->json([
        'success' => true,
        'cart' => session('session_' . $id)
    ]);
}

Route配置

Route::post('/task/{id}/adding-assignment-session/{key}', [Taskmanager::class, 'addAssignmentQuantity'])->name('add_assignment_quantity');

内容的提问来源于stack exchange,提问作者Amir Adamov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:28:09