【问题标题】:Doctrine - how to get the SQL INSERT query, in the postSave() event?Doctrine - 如何在 postSave() 事件中获取 SQL INSERT 查询?
【发布时间】:2011-03-24 15:50:10
【问题描述】:

我想获得在调用对象的 save() 方法时 Doctrine 生成的确切 SQL INSERT 查询。

最好是在模型的 postSave() 事件中获取,并记录在一个txt文件中。

例如:

<?php 
$user = new User(); // A Doctrine Model with timestampable behavior enabled
$user->first_name = 'Manny';
$user->last_name = 'Calavera';
$user->save();
?>

我想获取/记录以下 SQL 查询:

INSERT INTO user (first_name, last_name, created_at, updated_at) VALUES ('Manny', 'Calavera', '2010-08-03 12:00:00', '2010-08-03 12:00:00');

需要这个的背景是我希望稍后通过解析txt文件来批量导入数据。

【问题讨论】:

标签: php sql import doctrine


【解决方案1】:

您为什么不尝试看看 symfony 开发人员是如何做到的呢?检查他们的 WebDebug 工具栏以了解 Doctrine here。 WebDebug 工具栏输出您在页面上执行的所有查询。

DoctrineEvent 上有一个钩子,我想你可以修改代码来做你想做的事。检查getDoctrineEventsgetSqlLogs 方法。

希望这会有所帮助。如果您需要进一步解释,请写在评论中,我会尽力解释。

【讨论】:

    【解决方案2】:

    您可以使用 sfDoctrineDatabase 类中的分析器。使用 getQueryExecutionEvents 获取所有查询。

    $databaseManager = sfContext::getInstance()->getDatabaseManager();
    if ($databaseManager) {
        foreach ($databaseManager->getNames() as $name) {
            $database = $databaseManager->getDatabase($name);
            if ($database instanceof sfDoctrineDatabase && $profiler = $database->getProfiler()) {
                foreach ($profiler->getQueryExecutionEvents() as $event) {
                    $conn = $event->getInvoker() instanceof Doctrine_Connection ? $event->getInvoker() : $event->getInvoker()->getConnection();
                    $params = sfDoctrineConnectionProfiler::fixParams($event->getParams());
                    $query = $event->getQuery() ;
    
                    foreach ($params as $param) {
                        $param = htmlspecialchars($param, ENT_QUOTES, sfConfig::get('sf_charset'));
                        $query = join(var_export(is_scalar($param) ? $param : (string) $param, true), explode('?', $query, 2));
                    }
                    // log the $query here, or use the symfony's logger
                    // sfContext::getInstance()->getLogger()->debug(sprintf('Query Run !! %s ', $query));
                }
            }
        }
    }
    

    不要忘记使用参数加入查询(因此它将替换 ? 与值)

    :D

    【讨论】:

    • 别忘了在 $event->getQuery() 之前加上一些条件,可以使用 "if ( !(stripos($event->getQuery,'INTO log')) && (strtoupper (substr($event->getQuery(), 0, 6)) != 'SELECT') && strtoupper(substr($event->getQuery(), 0, 3)) != 'SET')"
    【解决方案3】:

    您可以通过此函数将您的 DQL 查询转换为 SQL:http://tokarchuk.ru/2010/12/dql-query-to-raw-sql/

    【讨论】:

      【解决方案4】:

      看看这里:http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql 并转到标题为 Profiling with Doctrine创建 Profiler Hook 的部分。尽管这是为了与 CodeIgniter 框架一起使用,但它可以很容易地用于您自己的环境,因为代码不依赖于框架。

      您基本上想设置一个连接分析器并让它将所有查询写入文件。我建议将所有查询附加到文件中以获得更好的类似“日志”的感觉。不要被文章中的许多框架讨论所迷惑。这些示例在其他场景中效果很好(稍加理解和复制粘贴)。

      【讨论】:

        【解决方案5】:

        我认为没有任何简单的方法可以做到这一点,因为 save() 的行为取决于一些不同的事情(如果您正在插入/更新)。

        如果您已经创建了一个学说查询对象,那么您可以像这样调用 getSqlQuery() 方法:

        $q = Doctrine_Query::create()
        ->select('u.id')
        ->from('User u');
        
        echo $q->getSqlQuery();
        

        但是 save() 是一个方法,而不是一个对象,所以这不起作用。我认为您必须编写一些代码来检测您是在插入还是更新并构建查询以即时登录,然后使用 save()。

        我知道这个建议并不理想,因为它没有“准确”记录 save() 正在做什么,但出于您所说的目的,它应该仍然可以正常工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-26
          • 2015-11-09
          • 2020-01-25
          • 1970-01-01
          相关资源
          最近更新 更多