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

基于多选列表实现USERVIDEOS数据库增删的问题求助

双栏多选列表数据库同步问题

我正在开发一个双栏多选列表功能:左栏展示全部未选中的视频,右栏展示用户已选中的视频。提交表单时,需要把右栏新增的视频添加到USERVIDEOS数据库,同时移除右栏中用户取消选择的条目,最终让USERVIDEOS只保留右栏当前的所有视频记录。

目前遇到的问题是:现有代码执行时会删除除本次选中项外的所有条目,无法仅移除用户取消选择的内容。

原PHP处理代码

if($_SERVER["REQUEST_METHOD"] == "POST") {
    if (isset($_POST['user-videos'])) {
        try {
            $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $stmt = $conn->prepare("DELETE FROM USERVIDEOS WHERE userID = :userID AND videoID NOT IN (:videos)");
            $stmt->bindParam(':userID', $userID);
            $stmt->bindValue(':videos', implode(",", $_POST['user-videos']));
            $stmt->execute();
            // Add the new Videos
            $stmt = $conn->prepare("INSERT INTO USERVIDEOS (userID, videoID) VALUES (:userID, :videoID)");
            $stmt->bindParam(':userID', $userID);
            $selected = $_POST['user-videos'];
            foreach ($selected as $videoID) {
                $stmt->bindParam(':videoID', $videoID);
                $stmt->execute();
            }
        } catch (PDOException $e) {
            echo 'Error: ' . $e->getMessage();
        }
    }
}

原HTML代码

<div class="form_container">
    <form name="videos" method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
    <div class="lvids">
        <label for="video-list">Database Videos:</label>
        <select class="videolist" id="video-list" size="10" name="video-list[]" multiple>
        <?php
            try {
                $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
                $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                // Retrieve all video IDs from the USERVIDEOS table
                $stmt1 = $conn->prepare("SELECT videoID FROM USERVIDEOS WHERE userID = :userID");
                $stmt1->bindParam(':userID', $userID);
                $stmt1->execute();
                $filterVideos = $stmt1->fetchAll(PDO::FETCH_COLUMN, 0);

                if(sizeof($filterVideos) != 0) {
                    $stmt2 = $conn->prepare("SELECT ID, videotitle FROM VIDEOS WHERE ID NOT IN (".implode(',', $filterVideos).") ORDER BY categorie ASC");
                    $stmt2->execute();
                    while ($row = $stmt2->fetch(PDO::FETCH_ASSOC)) {
                        echo "<option value='" . $row['ID'] . "'>" . $row['videotitle'] . "</option>";
                }
                } else {
                    $stmt = $conn->prepare("SELECT ID, videotitle FROM VIDEOS ORDER BY categorie ASC");
                    $stmt->execute();
                    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                        echo "<option value='" . $row['ID'] . "'>" . $row['videotitle'] . "</option>";
                    }
                }         
            } catch (PDOException $e) {
                echo 'Error: ' . $e->getMessage();
            }

            $conn = null;
            $stmt = null;
        ?>
        </select>
    </div>

    <div class="button_container">
        <input class="btn" type="button" value=">>" id="add-btn">
        <input class="btn" type="button" value="<<" id="remove-btn">
    </div>

    <div class="uvids">
        <label for="user-videos">Selected Videos:</label>
        <select class="uservideos" id="user-videos" size="10" name="user-videos[]" multiple>
        <?php 
            try {
                $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
                $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $stmt = $conn->prepare("SELECT VIDEOS.ID, VIDEOS.videotitle FROM VIDEOS 
                                        JOIN USERVIDEOS ON USERVIDEOS.videoID = VIDEOS.ID 
                                        WHERE USERVIDEOS.userID = :userID");
                $stmt->bindParam(':userID', $userID);
                $stmt->execute();
                $result = $stmt->fetchAll();
                foreach($result as $row) {
                    echo "<option value='" . $row['ID'] . "'>" . $row['videotitle'] . "</option>";
                }
            } catch (PDOException $e) {
                echo 'Error: ' . $e->getMessage();
            }
        ?>
        </select>
    </div>

    <br><br>
    <input type="submit" value="Upload Videos">
    </form>
</div>

问题分析与解决方案

问题根源

  1. PDO参数绑定错误:NOT IN (:videos)中,绑定的拼接字符串会被当作单个值,导致数据库认为是匹配videoID != "1,2,3"这类条件,而非排除多个ID。
  2. 重复插入数据:循环插入所有选中视频,若记录已存在会触发主键冲突(假设userID+videoID是联合主键)。
  3. 未处理空选择场景:当用户取消所有选择时,$_POST['user-videos']不存在,会跳过删除逻辑,导致旧记录残留。

修正后的PHP代码

if($_SERVER["REQUEST_METHOD"] == "POST") {
    try {
        $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        
        // 处理用户的选中视频,空值则设为空数组
        $selectedVideos = isset($_POST['user-videos']) ? array_map('intval', $_POST['user-videos']) : [];
        
        // 1. 删除用户取消选择的视频
        if (!empty($selectedVideos)) {
            // 为每个ID创建占位符
            $placeholders = implode(',', array_fill(0, count($selectedVideos), '?'));
            $stmt = $conn->prepare("DELETE FROM USERVIDEOS WHERE userID = ? AND videoID NOT IN ($placeholders)");
            // 绑定userID和所有选中的videoID
            $params = array_merge([$userID], $selectedVideos);
            $stmt->execute($params);
        } else {
            // 无选中时删除该用户所有记录
            $stmt = $conn->prepare("DELETE FROM USERVIDEOS WHERE userID = ?");
            $stmt->execute([$userID]);
        }
        
        // 2. 插入新增的视频(避免重复)
        if (!empty($selectedVideos)) {
            // 使用INSERT IGNORE或ON DUPLICATE KEY UPDATE避免重复插入
            $stmt = $conn->prepare("INSERT IGNORE INTO USERVIDEOS (userID, videoID) VALUES (?, ?)");
            $stmt->bindParam(1, $userID);
            foreach ($selectedVideos as $videoID) {
                $stmt->bindParam(2, $videoID);
                $stmt->execute();
            }
        }
        
        echo "视频列表已同步成功";
    } catch (PDOException $e) {
        echo 'Error: ' . $e->getMessage();
    } finally {
        $conn = null;
    }
}

关键改进点

  • 动态生成占位符:为每个选中的videoID创建独立的?占位符,确保NOT IN条件正确生效。
  • 处理空选择:当用户取消所有视频选择时,直接清空该用户的USERVIDEOS记录。
  • 避免重复插入:使用INSERT IGNORE(需确保userID+videoID是联合主键/唯一约束),或者INSERT ... ON DUPLICATE KEY UPDATE来跳过已存在的记录。
  • 数据安全:用array_map('intval', ...)确保videoID是整数,防止SQL注入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:30:41