2010-04-28 35 views
3

我已经检查了如this one (How do I create a PDO parameterized query with a LIKE statement in PHP)这样的问题的答案。 我已经结束了该解决方案:PDO/Php LIKE声明和特殊字符问题

$sql = "SELECT count(*) ". 
     "FROM mytable ". 
     "WHERE num_certif LIKE CONCAT('%',:val,'%')"; 
$valeur = 'azert'; 
$stmt = $pdo->prepare($sql); 
$stmt->bindValue(':val', $val); 

这工作,但这里是我的问题:我该如何处理“”字符? (即$ valeur ='%';返回所有行)?

回答

4

您需要将%字符转义,

$valeur = '\%'; 
+0

是啊,我知道这一点。但是,如果你考虑一下原则:prepare()和bindValue()已经为优化*和*做了避免函数,例如mysql_real_escape(),escape()等等,所以如果我必须做一个str_replace('%',' \%'...)这意味着有一个(重要的)目标错过了,这就是为什么我寻找一个优雅的解决方案,而不是回到旧的“php safe_mode”时间 – 2010-04-29 14:04:52

+0

我没有得到你的准备好的语句与通配符的语义没有任何关系,当用作准备语句的参数时,通配符不应改变它的含义 – 2010-04-29 14:55:50

+0

我的意思是:旧代码=“select * from xx where t =”。mysql_real_escape(blabla)。“
新代码:prepare(“select * from xx where t =:tmp”)then bindValue(':tmp',$ val)。使用你的建议,这会给:bindValue(':tmp',str_replace('%','\%',$ val))。这对我来说不是干净的代码。我们不应该在这里使用str_replace()。必须有另一种方式,因为这种方式是“逃避不需要的字符”的原则,这是一个原则,**应该**不再存在,这要归功于prepare()和bindValue()。我希望我这次更清楚:) – 2010-04-30 09:33:59

-1

为了避免做自己的转义,需要的东西进行转义必须是PDO保护数据,即部分必然的论点。它不能保护你免受硬编码查询中的任何事情的困扰。

$sql = "SELECT count(*) ". 
    "FROM avs_souscript ". 
    "WHERE num_certif =\"\" ". 
    "AND date_annul=\"\" ". 
    "AND user=:sess_user ". 
    "AND user!=\"\" ". 
    "AND num_certif LIKE :num_certif_search"; 
$valeur = 'azert'; //I assume this actually came from some user input 
$stmt = $pdo->prepare($sql); 
$stmt->bindValue(':num_certif_search', '%'.$valeur.'%'); 

(或交替,你可以把它们放在$valuer = "%{$userInput}%";分配,无论哪种方式,他们应该是在绑定的参数,而不是在SQL。

从SQL出移动傻字符串连接的该位到PHP也用于制造可扩展的应用很好的练习,它更容易扩展的Web服务器群比它规模数据库服务器

+0

非常感谢您的回答,但是......我做到了这一点,所以我不再需要关心美元价格。有了你的代码,我不得不关心$美元中的内容。假设$ valeur是从POST中读取的,它只是“*”字符。猜猜会发生什么?所有行都返回。 (无论如何,这就是我的示例代码中发生的事情,所以您的答案不是正确的解决方案)。有了你的代码,我不得不转义字符,我的问题就像是:“如何避免**被迫在代码php中转义字符?我不想修改什么是pdo应该处理它自己”。 – 2010-12-08 17:34:51

+0

PDO只能保护您免受用户输入。它假定SQL是安全的/理智的。如果你想保护(所有的逃避都是),要保护的值必须通过参数。它不会猜测通配符变量的语法以及如何解释你想要做的事情。你需要这样做。你似乎认为PDO不是。 – cabbey 2010-12-08 19:24:08

+0

从手册:'PDO提供了一个数据访问抽象层,这意味着无论您使用哪个数据库,您都使用相同的函数来发出查询和获取数据。 PDO不提供数据库抽象;它不会重写SQL或模拟缺少的功能。如果你需要这个设施,你应该使用一个完整的抽象层。' – cabbey 2010-12-08 19:24:39

0

我实现了使用字符串比较函数:。

WHERE INSTR(LCASE(num_certif),LCASE(:val))>0 

我怀疑表现会受到影响。

+1

你的评论是正确的:性能遭受*很多*。 **':/'** – 2012-09-17 06:45:52

+0

@Oiviv Pons感谢您验证。在我的情况下,这并不重要,我宁愿选择更优雅的解决方案。 – 2012-09-17 21:07:27

2

注意PostgreSQL的用户...而不是CONCAT功能,您可以使用

SELECT count(*) 
    FROM mytable 
    WHERE num_certif LIKE '%' || :val || '%' 
+0

伟大的提示!谢谢! – 2015-01-28 16:52:22

0
我一直使用的东西很简单,像这样

$select_str = "SELECT * FROM table_x WHERE text_field LIKE '%".$value."%'"; 

    $StHandler = $this->dbHandler->prepare($select_str); 
    $StHandler->execute(); 

只能使用一个%取决于你在找什么。例如,如果你想让它开始与你的价值,后来有任何字符,你会用“”。$值。“%'”

希望这有助于