好的,所以我对php和mysql相当新。我正在为mysql数据库创建一个php前端。我正在使用PDO驱动程序来访问数据库,因为它可以防止sql注入攻击。到目前为止,一直没问题,直到我遇到这个问题。我有一个搜索功能,用户可以输入公司名称full或partial来搜索有关它的数据。
这是我用来在数据库中进行搜索的PDO语句:
SELECT CompName FROM CompanyName
WHERE CompName REGEXP :name
ORDER BY CompName ASC LIMIT 1
然后我可以准备,将搜索字段中的用户类型绑定到参数名称并执行该语句。只要用户不键入任何元字符,它就可以工作。这是我插入PDO语句而不是名称的非常基本的正则表达式:
^ whatusertyped -since最初我正在寻找一个完整的匹配。由于某些公司名称确实包含句点,因此我希望用户能够键入这些字符和我的正则表达式,将它们作为文字而不是元字符。到目前为止,这就是我如何替换元字符以获得字面含义:
用户类型:C。查找以C开头的公司名称。
php函数插入^和\\\\以获得^ C \\。
的输出mysql获取:^ C \\。并在公司名称的开头搜索C.其中句号是字面意思而不是说"寻找外卡字符"。
所以我正在尝试使用C.因为数据库中有一家公司的名字就是这样开始的,我应该得到一个匹配,但是我不会,PDO语句会返回一个空数组。
我确实尝试过查询:
SELECT CompName FROM CompanyName
WHERE CompName REGEXP "^C\\\\."
ORDER BY CompName ASC LIMIT 1
直接在mysql中获得了一个匹配,我也直接在PHP中执行了查询而没有准备,绑定并返回匹配。在我看来,问题在于准备并将搜索词绑定到参数,但我无法弄清楚它究竟是什么以及如何解决它。我真的想使用bind和就像我说的那样准备避免sql注入。
非常感谢任何帮助。希望我能清楚地解释这个问题。
答案 0 :(得分:4)
我认为您绑定到:name
的价值应该只是^C\.
,而不是^C\\.
。您不需要为 sql 级别进行任何转义,只需要 regex 级别(即\.
为文字.
)
另外,请考虑使用WHERE CompName LIKE 'C.%'
。你这里不需要正则表达式。你会这样使用:
function like_escape($s) {
// Do like-expression escaping
return addcslashes($s, '%_');
}
$searchprefix = 'C.';
$sql = 'SELECT CompName FROM CompanyName WHERE CompName LIKE ? ORDER BY CompName ASC';
$stmt = $db->prepare($sql);
$likeclause = like_escape($searchprefix).'%';
$db->bindValue(1, $likeclause, PDO::PARAM_STR);
$stmt->execute();