将原始 SQL 与 Doctrine 一起使用

Posted

技术标签:

【中文标题】将原始 SQL 与 Doctrine 一起使用【英文标题】:Using Raw SQL with Doctrine 【发布时间】:2011-02-16 00:37:18 【问题描述】:

我需要使用一些极其复杂的查询来在我的应用程序中生成报告。我使用 symfony 作为我的框架和学说作为我的 ORM。

我的问题是这样的:

将高度复杂的 sql 查询直接传递给 Doctrine 而不将它们转换为 Doctrine 查询语言的最佳方法是什么?我一直在阅读有关Raw_SQL 扩展的信息,但您似乎仍需要分段传递查询(如from())。有什么东西可以只转储一堆原始的 sql 命令吗?

【问题讨论】:

对不起,题外话了,但是您使用什么工具/库来生成应用程序报告?最好的问候! 现在?只是 SQL、原始 php 和胆量。 :D 【参考方案1】:

Symfony 使用教义插入原始 sql。

这在 Symfoney 1.3 版本中

$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute($query);

【讨论】:

【参考方案2】:

应该注意的是,Doctrine2 使用 PDO 作为基础,因此我建议使用准备好的语句而不是普通的旧执行。

例子:

$db = Doctrine_Manager::getInstance()->getCurrentConnection();
$query = $db->prepare("SELECT `someField` FROM `someTable` WHERE `field` = :value");
$query->execute(array('value' => 'someValue'));

【讨论】:

这个问题是关于 Symfony 1。在 Symfony 1 上,使用了 Doctrine 1.2 - 这个答案可能有误导性。 对不起,我不是故意误导。该解决方案仍然有效,因为 Symfony 1 也可以与 Doctrine 一起使用。【参考方案3】:

你也可以使用 Doctrine_RawSql();创建原始 SQL 查询,这些查询将与学说对象相结合。

【讨论】:

【参考方案4】:
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute(" -- RAW SQL HERE -- ");

请参阅 Doctrine API 文档了解不同的执行方法。

【讨论】:

@simple:是的,你可以使用任何你想要的 SQL。 由于这个答案似乎很受欢迎,我应该补充一点,这个方法绕过了 Doctrine 提供的转义,所以手动转义东西,否则你可能会让自己面临 SQL 注入漏洞。 在我看来,这个答案适用于 Doctrine 版本 forum.symfony-project.org/viewtopic.php?f=23&t=37872 我发现在 @richsage 的回答中添加 ->getDbh() 可以防止在启用原则分析器时出现警告。【参考方案5】:

我不确定你说 raw SQL 是什么意思,但你可以这样执行传统的 SQL 查询:

... 
// $this->_displayPortabilityWarning();

$conn = Doctrine_Manager::connection();
$pdo = $conn->execute($sql);
$pdo->setFetchMode(Doctrine_Core::FETCH_ASSOC);
$result = $pdo->fetchAll();
...

以下方法不是必需的,但它显示了一个很好的做法。

protected function _displayPortabilityWarning($engine = 'pgsql')

     $conn = Doctrine_Manager::connection();
     $driver = $conn->getDriverName();

     if (strtolower($engine) != strtolower($driver)) 
        trigger_error('Here we have possible database portability issue. This code was tested on ' . $engine . ' but you are trying to run it on ' . $driver, E_USER_NOTICE);
     

【讨论】:

【参考方案6】:

是的。您可以使用以下代码从 Doctrine 获取数据库句柄:

$pdo = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh();

然后执行你的SQL如下:

$query = "SELECT * FROM table WHERE param1 = :param1 AND param2 = :param2";
$stmt = $pdo->prepare($query);

$params = array(
  "param1"  => "value1",
  "param2"  => "value2"
);
$stmt->execute($params);

$results = $stmt->fetchAll();  

你可以像上面的例子一样使用绑定变量。

请注意,Doctrine 不会自动将您的结果很好地融合到记录对象等中,因此您需要处理作为数组返回的结果,每行返回一个数组(键值作为列值)。

【讨论】:

有没有办法强制学说来补充我通过 PDO 获得的结果?还是我只需要使用我得到的东西? 从我使用上述内容时的记忆中,不是自动的,因为 Doctrine 不知道你有哪些列。如果您对列的命名足够好,我想您可以使用 fromArray() 或类似名称,但需要将数据重新格式化为可用的格式。 如果可以,请使用查询返回记录 ID,然后使用普通的旧 $table->find($id) 加载它。

以上是关于将原始 SQL 与 Doctrine 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 3.3 Doctrine Fixtures 加载跳过 SQL 视图

将 Doctrine 的 EntityRepository::matching() 方法与 Criteria 对象一起使用时,如何绑定参数?

将 Codeigniter 2 与 Doctrine ORM 2 < PHP v5.2 一起使用

symfony2 / 学说:如何将 ResultSetMapping 与计数一起使用

将原始 MySQL 翻译成 Doctrine 1.2

将 do() 与列表元素的名称一起使用