Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用条令querybuilder正确转义相似查询_Php_Mysql_Doctrine Orm_Sql Like - Fatal编程技术网

Php 使用条令querybuilder正确转义相似查询

Php 使用条令querybuilder正确转义相似查询,php,mysql,doctrine-orm,sql-like,Php,Mysql,Doctrine Orm,Sql Like,我正在尝试使用Doctrine QueryBuilder进行类似的查询。我读过很多其他的问题和文章,我必须正确地避开这种类型的质疑,但我不明白教义本身是否做到了这一点。以这些数据为例: my_column ABC ABCD A%BCD 和以下输入数据 ABC ABCD A A% 我期望这些结果: SELECT * FROM my_table WHERE my_column LIKE "%ABC%" => ABC, ABCD SELECT * FROM my_table WHERE my

我正在尝试使用Doctrine QueryBuilder进行类似的查询。我读过很多其他的问题和文章,我必须正确地避开这种类型的质疑,但我不明白教义本身是否做到了这一点。以这些数据为例:

my_column
ABC
ABCD
A%BCD
和以下输入数据

ABC
ABCD
A
A%
我期望这些结果:

SELECT * FROM my_table WHERE my_column LIKE "%ABC%" => ABC, ABCD
SELECT * FROM my_table WHERE my_column LIKE "%ABCD%" => ABCD
SELECT * FROM my_table WHERE my_column LIKE "%A%" => ABC, ABCD, A, A%
SELECT * FROM my_table WHERE my_column LIKE "%A%%" => A%
我的问题涉及最新的查询(和输入数据)。我应该如何正确地回避这个问题?是
“%”。addcslashes($input,'%.''.''.'输入''够了吗

如果可以的话,我准备了这个SQL提琴:

正如John Kary在gist中发现的那样,条令不像查询语句那样逃避
。更具体地说,它使用准备好的语句(如反斜杠或引号等字符被正确转义)转义参数,但是像
%
\
之类的字符(它们是
之类的
语句语法的一部分)不会被转义,输入也不会被清除。下面链接的要点提供了一个很好的解决此问题的方法,经过Symfony 2.6和Doctrine 2.5测试,效果非常好。为了确保要点不会被删除,我将代码复制到这里:

<?php
namespace Foo;

/**
 * Methods for safe LIKE querying.
 */
trait LikeQueryHelpers
{
    /**
     * Format a value that can be used as a parameter for a DQL LIKE search.
     *
     * $qb->where("u.name LIKE (:name) ESCAPE '!'")
     *    ->setParameter('name', $this->makeLikeParam('john'))
     *
     * NOTE: You MUST manually specify the `ESCAPE '!'` in your DQL query, AND the
     * ! character MUST be wrapped in single quotes, else the Doctrine DQL
     * parser will throw an error:
     *
     * [Syntax Error] line 0, col 127: Error: Expected Doctrine\ORM\Query\Lexer::T_STRING, got '"'
     *
     * Using the $pattern argument you can change the LIKE pattern your query
     * matches again. Default is "%search%". Remember that "%%" in a sprintf
     * pattern is an escaped "%".
     *
     * Common usage:
     *
     * ->makeLikeParam('foo')         == "%foo%"
     * ->makeLikeParam('foo', '%s%%') == "foo%"
     * ->makeLikeParam('foo', '%s_')  == "foo_"
     * ->makeLikeParam('foo', '%%%s') == "%foo"
     * ->makeLikeParam('foo', '_%s')  == "_foo"
     *
     * Escapes LIKE wildcards using '!' character:
     *
     * ->makeLikeParam('foo_bar') == "%foo!_bar%"
     *
     * @param string $search        Text to search for LIKE
     * @param string $pattern       sprintf-compatible substitution pattern
     * @return string
     */
    protected function makeLikeParam($search, $pattern = '%%%s%%')
    {
        /**
         * Function defined in-line so it doesn't show up for type-hinting on
         * classes that implement this trait.
         *
         * Makes a string safe for use in an SQL LIKE search query by escaping all
         * special characters with special meaning when used in a LIKE query.
         *
         * Uses ! character as default escape character because \ character in
         * Doctrine/DQL had trouble accepting it as a single \ and instead kept
         * trying to escape it as "\\". Resulted in DQL parse errors about "Escape
         * character must be 1 character"
         *
         * % = match 0 or more characters
         * _ = match 1 character
         *
         * Examples:
         *      gloves_pink   becomes  gloves!_pink
         *      gloves%pink   becomes  gloves!%pink
         *      glo_ves%pink  becomes  glo!_ves!%pink
         *
         * @param string $search
         * @return string
         */
        $sanitizeLikeValue = function ($search) {
            $escapeChar = '!';
            $escape = [
                '\\' . $escapeChar, // Must escape the escape-character for regex
                '\%',
                '\_',
            ];
            $pattern = sprintf('/([%s])/', implode('', $escape));
            return preg_replace($pattern, $escapeChar . '$0', $search);
        };
        return sprintf($pattern, $sanitizeLikeValue($search));
    }
}

只要使用参数就可以了。将%符号应用于数据。”选择。。。比如?'setParameter(0,%,'ABC'.%')根据要点,我应该将输入数据转义给自己。按照您的建议使用setParameter会返回不正确的结果(ABC、ABCD、A、A%),我不确定您链接的要点的上下文。DQL上有大量的错误信息。也许这本手册会有所帮助:(例如,搜索LIKE)。如果您得到了意外的结果,那么您可以仔细查看实际的查询。也许用真实的代码更新你的问题。但我100%相信,在使用参数化语句时,您不需要显式转义数据。对于引号或反斜杠等字符,参数化语句不需要显式转义,但是LIKE语句显然不能正确地转义像%或uu这样的字符,从而生成一个SQL查询,就像我在fiddle中写的上一个查询一样。要将该字符视为文字,必须进行手动转义,如链接的要点所示。剩下的唯一问题是为什么转义字符本身被转义。不管这里的最终答案是什么,我觉得我应该指出,包含“%”…%”
之类的
的查询对性能非常有害。您基本上是告诉DB加载每一条记录并逐个解析它们来搜索字符串,然后丢弃不匹配的记录。如果您的数据库甚至有中等数量的记录,那么这种查询的运行速度将非常慢。甚至不要考虑加入。如果需要的话,有一些很好的方法可以进行复杂的搜索<代码>如%…%
不是这些方法之一。这似乎是不必要的。当您使用准备好的语句时,不需要逃避参数。请参阅:引用答案,Doctrine确实会转义输入参数,但不会转义LIKE SQL语句的语法,因此,如果在参数值内加引号,则会转义,但是,如果您在参数中添加%符号,则不会出现安全问题,这将使您的应用程序面临安全问题。由于参数中包含%不会带来安全风险,因此不会导致SQL注入之类的问题。如果要使用%作为文字或通配符,则由您决定。因此,这是您的设计决策。这是否是一个安全问题取决于您的设计。实际上,LIKE语句中不转义%是一个安全问题,因为它可能会导致应用程序的性能问题,因此是一个拒绝服务向量,如下所述:正如我所说,这取决于您的设计。我可能希望进行搜索,并在默认情况下使用%和limit子句。使用它可能是完全可以接受的。我知道有几种服务允许使用通配符。如果你所说的是真的,并且在100%的情况下这是一个安全风险,那么默认情况下它是可以逃脱的。
<?php
namespace Foo\Entity;

use Doctrine\ORM\EntityRepository;
use Foo\LikeQueryHelpers;

class ProductRepository extends EntityRepository
{
    use LikeQueryHelpers;
    /**
     * Find Product entities containing searched terms
     *
     * @param string $term
     * @return Product[]
     */
    public function findInSearchableFields($term)
    {
        return $this->createQueryBuilder('p')
            ->where("p.title LIKE :title ESCAPE '!'")
            ->setParameter('title', $this->makeLikeParam($term))
            ->getQuery()
            ->execute();
    }
}