views:

4745

answers:

3

So you can use something like this:

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

to examine the sql that the Zend Db Framework is going to use for that SELECT query. Is there an equivilent way to view the SQL for an update?

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

Use Zend_Db_Profiler to capture and report SQL statements:

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

Remember to turn the profiler off if you don't need it! I talked to one fellow who thought he had a memory leak, but it was the profiler instantiating a few PHP objects for each of the millions of SQL queries he was running.

PS: You should use quoteInto() in that query:

$n = $db->update('pages', $data, $db->quoteInto("url = ?", $content));
Bill Karwin
Thanks, that did it. Pointing me to the profiler helped me in other areas as well.
I only keep it turned on in dev.
joedevon
A: 

No, not directly, since Zend Framework builds and executes the SQL inside the adapter method Zend_Db_Adapter_Abstract::update:

/**
 * 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;
}

You can, temporarily, insert a var_dump and exit inside this method to inspect the sql to ensure that it is correct:

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

I quess another way is to log the actual SQL query, rather than changing the ZF library code, by combining the profiler data.

$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);

raphaelstolt
Have you tried this? It doesn't appear to work in ZF 1.9.5. When you give an array to quoteInto(), it joins it to a comma-separated string, and substitutes the result for each parameter placeholder. Also quoteInto() is not very smart about question marks inside string literals and it doesn't support named parameter placeholders at all.
Bill Karwin
No. I didn't try it was a wild guess based on the Zend_Db_Profiler and Zend_Db API. Thanks for verifying ;D
raphaelstolt