你怎么逃避教义?

时间:2013-12-12 08:20:45

标签: php doctrine-orm

你怎么逃避教义?

我制作了这段代码

$query = $em->createQuery(
                "SELECT a FROM AcmeTopBundle:ArtData a WHERE
                a.name = '". mysql_escape_string($name) ."'");

但是$ name是A'z

它返回错误

[Doctrine\ORM\Query\QueryException]          
SELECT a FROM AcmeTopBundle:ArtData a WHERE  
                a.name = 'A\'s'  

我认为在使用原始sql时我被mysql_escape_string转义。

如何在学说上避免这个错误?

5 个答案:

答案 0 :(得分:12)

我通常使用的方法是使用参数和querybuilder(https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html)...

$qb = $em->createQueryBuilder(
            "SELECT a FROM AcmeTopBundle:ArtData a WHERE
            a.name = :name")
     ->setParameter('name',$name);
$result = $qb->getQuery()->execute();

答案 1 :(得分:4)

基于https://stackoverflow.com/a/13377430/829533

您可以使用预备语句http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#using-prepared-statements

来自文档:

$date = new \DateTime("2011-03-05 14:00:21");
$stmt = $conn->prepare("SELECT * FROM articles WHERE publish_date > ?");
$stmt->bindValue(1, $date, "datetime");
$stmt->execute();

答案 2 :(得分:2)

这不能解答您的问题,但会解释您的代码出了什么问题。它不符合评论。

您不能也不应该使用mysql_escape_string()

  • 这是错误的转义函数,正确的转义函数曾是mysql_real_escape_string()。阅读the documentation听起来并不像,但为了正确逃避,您必须知道正在使用哪种字符编码。在西方编码方案中,如ASCII,ISO-8859-x甚至UTF-8,它可能没有什么区别,但是有一些奇特的中文编码,绝对需要知道"字节是否属于另一个字节或者是自己的。
  • 使用mysql_real_escape_string()时,需要使用mysql_connect()创建已打开的数据库连接。如果不这样做,PHP会尝试使用php.ini文件中定义的默认用户和密码打开新连接。这通常会导致错误,因为没有密码,数据库将不允许您执行任何操作。另外,如果你成功了,那么这个连接的编码设置很可能不是Doctrine使用的那个。
  • 使用任何mysql_ *函数都是错误的,因为这些函数已被弃用。正确的方法是使用mysqli_ * functions。
  • Doctrine可以使用三种数据库连接方法中的任何一种:mysql,mysqli或PDO。如果要手动调用正确的转义函数,则必须选择真正使用的那个。虽然已经创建了连接。并且不知何故,您需要获取该连接资源以允许您调用的函数检测使用的编码。

所以最后有很多理由说明为什么只是使用任何逃避声音就像是在做这项工作一样是错误的。

正确的方法是使用您正在使用的数据库层的转义。如果您使用Doctrine,则使用它进行转义。或者更好,避免转义,使用预准备语句或查询构建器,让Doctrine处理剩下的事情。

答案 3 :(得分:1)

好吧,即使已经接受了答案,也没有疑问,因为它的标题如此。 @Sven的答案接近,但没有提及:

Doctrine documentation

  

要在这些情况下避免用户输入,请使用Connection#quote()方法。

我对“情景”感到不满,或者更多地是人们在推动准备好的陈述,例如一些圣杯。好吧,它们在理论上很不错,至少在PHP中它们实际上很笨拙,因为它们无法执行简单的操作,例如IN (<list>)或使用VALUES (<bla bla>), (<more stuff>)进行多次插入,这是一笔巨大的交易,如果没有最后,它很普遍地诉诸于不太理想的SQL(简而言之)(如果一个人至少在宗教上坚持使用准备好的语句,那就好了。)

答案 4 :(得分:0)

这将显示如何将数据插入到通常必须使用real_escape_string的数据库中。

Doctrine和Symfony 3使用编写的非QueryBuilder:

// get the post value
$value = $request->request->get('value'); 

$sql = "INSERT INTO `table_name`
(`column_name1`,`column_name2`)
VALUES
('Static Data',?)
";

$em = $this->getDoctrine()->getManager();
$result = $em->getConnection()->prepare($sql);
$result->bindValue(1, $value);
$result->execute(); 

如果您使用自动增量记录,现在获得成功/失败的奖励:

$id = $em->getConnection()->lastInsertId();

如果$ id有值,则执行插入。如果没有插入失败。