Zend DB框架:检查更新查询

20

因此,您可以使用类似以下内容的代码:

$query = $db->select();
$query->from('pages', array('url'));
echo $query->__toString();

如何检查Zend Db Framework将为SELECT查询使用的SQL语句?是否有等效的方法可以查看UPDATE语句的SQL语句?

$data = array(
   'content'      => stripslashes(htmlspecialchars_decode($content))
);      
$n = $db->update('pages', $data, "url = '".$content."'");
??

1
与解决方案无关,但当一个对象被转换为字符串时,__toString()会自动调用,所以echo $query;更容易输入。 - chris
4个回答

33

使用 Zend_Db_Profiler 来捕获和报告 SQL 语句:

$db->getProfiler()->setEnabled(true);
$db->update( ... );
print $db->getProfiler()->getLastQueryProfile()->getQuery();
print_r($db->getProfiler()->getLastQueryProfile()->getQueryParams());
$db->getProfiler()->setEnabled(false);

如果你不需要使用,记得关闭分析器!我曾经和一个人交谈过,他认为他有内存泄漏,但实际上是因为分析器为他运行的数百万个SQL查询实例化了一些PHP对象。

PS:在那个查询中应该使用quoteInto()

$n = $db->update('pages', $data, $db->quoteInto("url = ?", $content));

谢谢,解决了我的问题。指引我使用分析器还帮助我在其他方面取得了进展。 - Chris C
我只在开发环境下保持它开启。 - joedevon
1
update()函数中的"where"部分能否接受数组?例如:$db->update('pages', $data, array("url = ?" => $content, "date > ?" => $date)); - caligoanimus
@caligoanimus:老实说,我不确定,我已经失去了对ZF项目的追踪。最好在ZF邮件列表上询问或自己阅读代码。 - Bill Karwin

2
不直接,因为 Zend Framework 在适配器方法 Zend_Db_Adapter_Abstract::update 中构建和执行 SQL。
/**
 * Updates table rows with specified data based on a WHERE clause.
 *
 * @param  mixed        $table The table to update.
 * @param  array        $bind  Column-value pairs.
 * @param  mixed        $where UPDATE WHERE clause(s).
 * @return int          The number of affected rows.
 */
public function update($table, array $bind, $where = '')
{
    /**
     * Build "col = ?" pairs for the statement,
     * except for Zend_Db_Expr which is treated literally.
     */
    $set = array();
    foreach ($bind as $col => $val) {
        if ($val instanceof Zend_Db_Expr) {
            $val = $val->__toString();
            unset($bind[$col]);
        } else {
            $val = '?';
        }
        $set[] = $this->quoteIdentifier($col, true) . ' = ' . $val;
    }

    $where = $this->_whereExpr($where);

    /**
     * Build the UPDATE statement
     */
    $sql = "UPDATE "
         . $this->quoteIdentifier($table, true)
         . ' SET ' . implode(', ', $set)
         . (($where) ? " WHERE $where" : '');

    /**
     * Execute the statement and return the number of affected rows
     */
    $stmt = $this->query($sql, array_values($bind));
    $result = $stmt->rowCount();
    return $result;
}

您可以在此方法中暂时插入var_dump和exit来检查SQL语句是否正确:
/**
 * Build the UPDATE statement
 */
 $sql = "UPDATE "
         . $this->quoteIdentifier($table, true)
         . ' SET ' . implode(', ', $set)
         . (($where) ? " WHERE $where" : '');
 var_dump($sql); exit;

0
我猜另一种方法是记录实际的SQL查询,而不是更改ZF库代码,通过组合分析器数据。
$db->getProfiler()->setEnabled(true);

$db->update( ... );

$query = $db->getProfiler()->getLastQueryProfile()->getQuery();

$queryParams = $db->getProfiler()->getLastQueryProfile()->getQueryParams();

$logger->log('SQL: ' . $db->quoteInto($query, $queryParams), Zend_Log::DEBUG);

$db->getProfiler()->setEnabled(false);

1
你试过这个吗?在ZF 1.9.5中似乎不起作用。当你给quoteInto()一个数组时,它会将其连接成逗号分隔的字符串,并将结果替换为每个参数占位符。此外,quoteInto()对于字符串字面值内部的问号并不十分智能,也完全不支持命名参数占位符。 - Bill Karwin
没有,我没有尝试过,这只是基于Zend_Db_Profiler和Zend_Db API的猜测。谢谢你的验证;D - raphaelstolt

0

最近在寻找一种调试zend_db_statement的方法时发现了这个。如果有其他人使用相同的搜索方式遇到此问题,可以使用以下函数。

只需将“self::getDefaultAdapter()”替换为您获取DB连接或适配器的方法即可。

/**
 * replace any named parameters with placeholders
 * @param string $sql sql string with placeholders, e.g. :theKey
 * @param array $bind array keyed on placeholders, e.g. array('theKey', 'THEVALUE')
 * 
 * @return String sql statement with the placeholders replaced
 */
public static function debugNamedParamsSql($sql, array $bind) {
    $sqlDebug = $sql;
    foreach($bind as $needle => $replace) {
        $sqlDebug = str_replace( 
                                ':' . $needle, 
                                self::getDefaultAdapter()->quote($replace), 
                                $sqlDebug
        );
    }        
    return $sqlDebug;        
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接