在search condition中使用LIKE运算符时:
<?php
array('OR' => array(
array('Post.title LIKE' => '%one%'),
array('Post.title LIKE' => '%two%')
))
... CakePHP中是否有内置机制来转义通配符,以便您可以搜索文字%
或_
或只是从不受信任的来源(如表单)中注入搜索词?
<?php
array('OR' => array(
array('Post.title LIKE' => '%' . $this->foo('100%') . '%'),
array('Post.title LIKE' => '%' . $this->foo('red_apples') . '%')
^^^
))
答案 0 :(得分:2)
App::uses('Sanitize', 'Utility'); // load Sanitize utility
$db = $this->Model->getDataSource(); // get the datasource
$this->Model->find('all', array(
'conditions' => array(
'name LIKE' => $db->expression('\'%' . addcslashes(Sanitize::escape($userInput), '%_') . '%\'')
)
));
当我们使用$db->expression
时,蛋糕不会为我们逃脱。因此,我们使用Sanitize
实用程序手动执行转义,然后将%
和_
替换为\%
和\_
。不确定这是否100%安全,请告诉我,如果您发现不是这样,我可以更新答案。
你需要创建自己的方法来完成这一切,让你保持干净
修改:将str_replace
替换为addcslashes
Edit2:意识到我过度复杂了。如果你想要蛋糕不能逃脱,你也可以只提供没有钥匙的价值。实施例
'conditions' => array(
'Post.title LIKE \'%' . addcslashes(Sanitize::escape($userInput), '%_') . '%\'',
)
两种方式都产生
`Post`.`title` LIKE '%100\'\%\_%'
表示用户输入$userInput = "100'%_";
答案 1 :(得分:0)
您必须使用Data Sanitization class来实现相同目标。希望它对你有用。
答案 2 :(得分:0)
我最终发现我可以简单地使用预先准备的语句:
<?php
$query = array('OR' => array(
array(
'Post.title LIKE ?' => array(
'%' . $this->escapeLike('100%') . '%'),
),
),
array(
'Post.title LIKE ?' => array(
'%' . $this->escapeLike('red_apples') . '%'),
),
),
);
...或者,只要DBMS没有默认分隔符,或者我们更愿意设置我们的分隔符:
<?php
$separator = '|';
$query = array('OR' => array(
array(
'Post.title LIKE ? ESCAPE ?' => array(
'%' . $this->escapeLike('100%', $separator) . '%'),
$separator
),
),
array(
'Post.title LIKE ? ESCAPE ?' => array(
'%' . $this->escapeLike('red_apples', $separator) . '%'),
$separator
),
),
);
我的escapeLike()
方法目前是这个(从来不是困难的部分):
/**
* Escapes LIKE wildcard characters
*
* @param string $text
* @param string $escape_character
* @return string
*/
protected function escapeLike ($text, $escape_character='\\') {
return strtr($text, array(
'%' => $escape_character . '%',
'_' => $escape_character . '_',
$escape_character => $escape_character . $escape_character,
));
}
为了简单起见,我在AppModel
中实现了它(至少在我的项目中)。
这适用于带有MySQL适配器的CakePHP / 2.5(不知道其他场景)。