如何使用正则处理标题实现GET请求替代ID传参并正确查询数据库
解决基于标题Slug的GET请求查询问题
看起来你遇到的核心问题有两个:SQL查询的语法/安全问题,以及标题转Slug的正则优化,咱们一步步来解决:
一、修复后端SQL查询的问题
你当前的查询SELECT * FROM vdoWHEREtitle=$vdo有两个致命问题:
- 字符串类型的字段值没有加单引号,数据库会把
$vdo当成标识符(比如字段名),直接触发语法错误 - 直接拼接用户输入到SQL语句中,存在严重的SQL注入风险
推荐方案:使用预处理语句(安全且规范)
以PDO为例(mysqli也支持类似的预处理逻辑):
// 假设你已经通过PDO建立了数据库连接$pdo if(isset($_GET['vdo'])) { $vdoSlug = trim($_GET['vdo']); // 先清理参数首尾的空格 // 准备预处理语句,用?作为占位符 $stmt = $pdo->prepare("SELECT * FROM `vdo` WHERE `title_slug` = ?"); $stmt->execute([$vdoSlug]); // 绑定参数并执行 $video = $stmt->fetch(PDO::FETCH_ASSOC); if($video) { // 找到对应视频,执行后续业务逻辑 } else { // 未找到视频,返回404页面或提示信息 } }
小建议:我推荐你在数据库里新增一个
title_slug字段,专门存储处理后的Slug值——原标题可能包含特殊字符,即使处理后也可能和其他标题生成重复的Slug,提前存储可以避免重复,查询效率也更高。
如果暂时不想修改数据库结构,用原标题查询的话,至少要给字符串加单引号并转义(但仍不如预处理安全):
// 仅作为临时过渡方案,不推荐长期使用 $vdo = mysqli_real_escape_string($conn, $_GET['vdo']); // $conn是你的mysqli连接 $get_v = "SELECT * FROM `vdo` WHERE `title`='$vdo'";
二、优化标题转Slug的正则处理
你当前的正则preg_replace('/[^A-Za-z0-9-]+/', '-', $title)会把非允许字符替换成减号,但会出现连续减号(比如标题是My first video!@#会变成My-first-video---),还有首尾可能残留减号,需要进一步处理:
function generateSlug($title) { // 1. 转小写(可选,让Slug风格更统一) $slug = strtolower($title); // 2. 替换非字母数字和减号的字符为减号 $slug = preg_replace('/[^a-z0-9-]+/', '-', $slug); // 3. 把连续的多个减号替换成单个减号 $slug = preg_replace('/-+/', '-', $slug); // 4. 去掉首尾的减号 $slug = trim($slug, '-'); return $slug; } // 使用示例 $title = "My first vido is here!!!"; $slug = generateSlug($title); // 输出:my-first-vido-is-here
三、前端链接的安全处理
生成前端链接时,要对Slug做URL编码+HTML转义,防止特殊字符导致的URL异常或XSS风险:
<a href="http://website.com/vdo.php?vdo=<?php echo htmlspecialchars(urlencode($slug)); ?>"> click here </a>
后端接收时,PHP会自动对$_GET['vdo']进行URL解码,所以不需要额外处理。
额外建议:处理Slug重复的情况
如果两个不同的标题生成了相同的Slug(比如My Video和My-Video),可以在Slug后面添加数字后缀区分,比如my-video-1、my-video-2。存储到title_slug字段前先检查是否存在,存在就递增数字后缀即可。
内容的提问来源于stack exchange,提问作者chetan kurkure
相关产品推荐
相关产品推荐

