PHP项目怎么实现商品上下架功能?

wen PHP项目 13

本文目录导读:

PHP项目怎么实现商品上下架功能?

  1. 数据库设计
  2. 后端实现
  3. 前端实现
  4. 安全考虑
  5. 高级功能扩展
  6. 最佳实践建议

在PHP项目中实现商品上下架功能,核心是设计数据库状态字段 + 后端逻辑控制 + 前端交互,下面是完整实现方案:

数据库设计

在商品表中添加状态字段:

CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    price DECIMAL(10,2),
    stock INT DEFAULT 0,
    status TINYINT DEFAULT 1 COMMENT '1=上架 0=下架',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

状态字段设计要点:

  • 建议用 TINYINTINT 类型
  • 值含义清晰:1 上架,0 下架
  • 后续扩展可加 2=待审核 等状态

后端实现

1 商品模型层

class Product {
    private $db;
    public function __construct($db) {
        $this->db = $db;
    }
    // 切换商品状态
    public function toggleStatus($productId) {
        $sql = "UPDATE products SET status = !status WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([$productId]);
    }
    // 设置指定状态
    public function setStatus($productId, $status) {
        $allowedStatus = [0, 1];
        if (!in_array($status, $allowedStatus)) {
            return false;
        }
        $sql = "UPDATE products SET status = ? WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([$status, $productId]);
    }
    // 批量操作
    public function batchSetStatus($productIds, $status) {
        if (empty($productIds)) return false;
        $placeholders = implode(',', array_fill(0, count($productIds), '?'));
        $sql = "UPDATE products SET status = ? WHERE id IN ($placeholders)";
        $params = array_merge([$status], $productIds);
        $stmt = $this->db->prepare($sql);
        return $stmt->execute($params);
    }
    // 获取在售商品
    public function getActiveProducts() {
        $sql = "SELECT * FROM products WHERE status = 1";
        return $this->db->query($sql)->fetchAll();
    }
}

2 控制器层

class ProductController {
    private $productModel;
    public function __construct($productModel) {
        $this->productModel = $productModel;
    }
    // 切换状态接口
    public function toggleStatus($request) {
        $productId = $request['id'] ?? 0;
        // 验证商品存在
        if (!$this->productExists($productId)) {
            return ['code' => 404, 'msg' => '商品不存在'];
        }
        $result = $this->productModel->toggleStatus($productId);
        if ($result) {
            return ['code' => 200, 'msg' => '状态切换成功'];
        } else {
            return ['code' => 500, 'msg' => '操作失败'];
        }
    }
    // 上下架操作接口
    public function updateStatus($request) {
        $productId = $request['id'] ?? 0;
        $status = $request['status'] ?? 0;
        // 权限验证
        if (!$this->checkPermission()) {
            return ['code' => 403, 'msg' => '无权限'];
        }
        $result = $this->productModel->setStatus($productId, $status);
        if ($result) {
            $action = $status == 1 ? '上架' : '下架';
            // 记录操作日志
            $this->logOperation($productId, $action);
            return ['code' => 200, 'msg' => "商品{$action}成功"];
        }
        return ['code' => 500, 'msg' => '操作失败'];
    }
}

前端实现

1 使用 AJAX 实现

<!-- 商品列表页面 -->
<div id="product-list">
    <table>
        <thead>
            <tr>
                <th><input type="checkbox" id="select-all"></th>
                <th>商品名称</th>
                <th>价格</th>
                <th>库存</th>
                <th>状态</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($products as $product): ?>
            <tr data-id="<?= $product['id'] ?>">
                <td><input type="checkbox" class="product-checkbox"></td>
                <td><?= htmlspecialchars($product['name']) ?></td>
                <td>¥<?= $product['price'] ?></td>
                <td><?= $product['stock'] ?></td>
                <td>
                    <span class="status-badge <?= $product['status'] ? 'active' : 'inactive' ?>">
                        <?= $product['status'] ? '上架' : '下架' ?>
                    </span>
                </td>
                <td>
                    <button class="btn-toggle-status" data-id="<?= $product['id'] ?>">
                        <?= $product['status'] ? '下架' : '上架' ?>
                    </button>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<!-- 批量操作按钮 -->
<div class="batch-actions">
    <button id="batch-on">批量上架</button>
    <button id="batch-off">批量下架</button>
</div>

2 JavaScript 交互

$(document).ready(function() {
    // 单个商品上架/下架切换
    $('.btn-toggle-status').click(function() {
        const productId = $(this).data('id');
        const $button = $(this);
        // 显示加载状态
        $button.prop('disabled', true).text('处理中...');
        $.ajax({
            url: '/api/product/toggle-status',
            method: 'POST',
            data: { id: productId },
            dataType: 'json',
            success: function(response) {
                if (response.code === 200) {
                    // 更新UI
                    const $row = $button.closest('tr');
                    const $badge = $row.find('.status-badge');
                    const $toggleBtn = $row.find('.btn-toggle-status');
                    // 切换状态显示
                    if ($badge.hasClass('active')) {
                        $badge.removeClass('active').addClass('inactive');
                        $badge.text('下架');
                        $toggleBtn.text('上架');
                    } else {
                        $badge.removeClass('inactive').addClass('active');
                        $badge.text('上架');
                        $toggleBtn.text('下架');
                    }
                    showToast('操作成功', 'success');
                } else {
                    showToast(response.msg || '操作失败', 'error');
                }
            },
            error: function() {
                showToast('网络错误,请重试', 'error');
            },
            complete: function() {
                $button.prop('disabled', false);
            }
        });
    });
    // 批量操作
    $('#batch-on, #batch-off').click(function() {
        const status = $(this).attr('id') === 'batch-on' ? 1 : 0;
        const selectedIds = [];
        // 收集选中的商品ID
        $('.product-checkbox:checked').each(function() {
            selectedIds.push($(this).closest('tr').data('id'));
        });
        if (selectedIds.length === 0) {
            showToast('请先选择商品', 'warning');
            return;
        }
        // 确认对话框
        if (!confirm(`确定要${status ? '上架' : '下架'}选中的${selectedIds.length}个商品吗?`)) {
            return;
        }
        $.ajax({
            url: '/api/product/batch-status',
            method: 'POST',
            data: {
                ids: selectedIds,
                status: status
            },
            dataType: 'json',
            success: function(response) {
                if (response.code === 200) {
                    location.reload();
                } else {
                    showToast(response.msg, 'error');
                }
            }
        });
    });
});

安全考虑

1 权限验证

// 中间件示例
class AuthMiddleware {
    public function handle($request) {
        // 只有管理员可以操作上架/下架
        if ($_SESSION['user_role'] !== 'admin') {
            header('HTTP/1.1 403 Forbidden');
            echo json_encode(['code' => 403, 'msg' => '无权限']);
            exit;
        }
    }
}

2 防止 SQL 注入

  • 始终使用预处理语句
  • 对输入进行验证和过滤
// 安全的查询
$stmt = $pdo->prepare("UPDATE products SET status = ? WHERE id = ?");
$stmt->execute([intval($status), intval($id)]);

高级功能扩展

1 定时上下架

// 创建定时任务表
CREATE TABLE schedule_products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    product_id INT,
    action TINYINT COMMENT '1=上架 0=下架',
    execute_time DATETIME,
    status TINYINT DEFAULT 0 COMMENT '0=待执行 1=已执行',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
// 定时任务脚本
class ScheduleTask {
    public function execute() {
        $sql = "SELECT * FROM schedule_products 
                WHERE status = 0 AND execute_time <= NOW()";
        $tasks = $this->db->query($sql)->fetchAll();
        foreach ($tasks as $task) {
            // 执行上下架操作
            $this->updateProductStatus($task['product_id'], $task['action']);
            // 更新任务状态
            $updateSql = "UPDATE schedule_products SET status = 1 WHERE id = ?";
            $this->db->prepare($updateSql)->execute([$task['id']]);
        }
    }
}

2 日志记录

CREATE TABLE product_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    product_id INT,
    action VARCHAR(50),
    operator INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_product_id (product_id)
);

最佳实践建议

  1. 使用事务:批量操作时使用事务确保数据一致性
  2. 缓存处理:频繁查询的商品状态可加入 Redis 缓存
  3. SEO 处理:下架商品返回 404 状态码,避免搜索引擎索引
  4. 前端优化:使用防抖处理,避免频繁点击导致多次请求
  5. 状态机模式:复杂状态流转建议使用状态机模式

这个实现方案适合大多数 PHP 项目,可以根据具体需求进行调整和扩展。

抱歉,评论功能暂时关闭!