在LIKE条件中转义通配符

时间:2012-08-14 06:12:35

标签: php mysql cakephp

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') . '%')
                                            ^^^
))

3 个答案:

答案 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(不知道其他场景)。