从Phalcon查询构建器获取原始sql

时间:2014-01-24 17:57:29

标签: phalcon

是否可以从Phalcon中的查询构建器实例中提取原始sql查询?像这样的东西?

$queryBuilder = new Phalcon\Mvc\Model\Query\Builder();
$queryBuilder
    ->from(…)
    ->where(…);

$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();

6 个答案:

答案 0 :(得分:14)

错误和审判下面似乎有效。如果有人能确认是否有更好的方法,那就太好了。

$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…);

$intermediate = $queryBuilder->getQuery()->parse();
$dialect      = DI::getDefault()->get('db')->getDialect();
$sql          = $dialect->select($intermediate);

修改:从2.0.3开始,您可以做到非常简单,有关详细信息,请参阅comment

$modelsManager->createBuilder()
    ->from('Some\Robots')
    ->getQuery()
    ->getSql()

答案 1 :(得分:2)

您可以在DbAdapter上使用getRealSqlStatement()(或类似的函数名称)。见http://docs.phalconphp.com/en/latest/api/Phalcon_Db_Adapter.html

根据文档,你可以通过这种方式得到sql查询。

或等等,这可能不适用于querybuilder。否则,您可以设置低级查询日志记录:http://docs.phalconphp.com/en/latest/reference/models.html#logging-low-level-sql-statements

答案 2 :(得分:1)

$db = Phalcon\DI::getDefault()->getDb();
$sql = $db->getSQLStatement();
$vars = $db->getSQLVariables();
if ($vars) {
    $keys = array();
    $values = array();
    foreach ($vars as $placeHolder=>$var) {
        // fill array of placeholders
        if (is_string($placeHolder)) {
            $keys[] = '/:'.ltrim($placeHolder, ':').'/';
        } else {
            $keys[] = '/[?]/';
        }
        // fill array of values
        // It makes sense to use RawValue only in INSERT and UPDATE queries and only as values
        // in all other cases it will be inserted as a quoted string
        if ((strpos($sql, 'INSERT') === 0 || strpos($sql, 'UPDATE') === 0) && $var instanceof \Phalcon\Db\RawValue) {
            $var = $var->getValue();
        } elseif (is_null($var)) {
            $var = 'NULL';
        } elseif (is_numeric($var)) {
            $var = $var;
        } else {
            $var = '"'.$var.'"';
        }
        $values[] = $var;
    }
    $sql = preg_replace($keys, $values, $sql, 1);
}

您可以阅读there

答案 3 :(得分:0)

如果您使用的是查询生成器,则如下所示,然后getPhql函数可以达到phalcon 3.4.4版本的目的。


    $queryBuilder = new Builder();
    $queryBuilder->from(…)->where(…)->getQuery();
    $queryBuilder->getPhql();

答案 4 :(得分:0)

if (!function_exists("getParsedBuilderQuery")) {
    /**
     * @param \Phalcon\Mvc\Model\Query\BuilderInterface $builder
     *
     * @return null|string|string[]
     */
    function getParsedBuilderQuery (\Phalcon\Mvc\Model\Query\BuilderInterface $builder) {
        $dialect = Phalcon\Di::getDefault()->get('db')->getDialect();
        $sql = $dialect->select($builder->getQuery()->parse());

        foreach ($builder->getQuery()->getBindParams() as $key => $value) {
            // For strings work fine. You can add other types below
            $sql = preg_replace("/:?\s?($key)\s?:?/","'$value'",$sql);
        }
        return $sql;
    }
}

我用于调试的简单函数。

答案 5 :(得分:0)

以下是常见的解决方案:

$result = $modelsManager->createBuilder()
            ->from(Foo::class)
            ->where('slug = :bar:', ['bar' => "some-slug"])
            ->getQuery()
            ->getSql();

但是您可能不希望看到没有查询值的查询,例如:

die(print_r($result, true));

Array
(
    [sql] => SELECT `foo`.`id`, `foo`.`slug` FROM `foo` WHERE `foo`.`slug` = :bar
    [bind] => Array
        (
            [bar] => some-slug
        )

    [bindTypes] => 
)

因此,这段简单的代码可能会有用:

public static function toSql(\Phalcon\Mvc\Model\Query\BuilderInterface $builder) : string
    {
        $data = $builder->getQuery()->getSql();

        ['sql' => $sql, 'bind' => $binds, 'bindTypes' => $bindTypes] = $data;

        $finalSql = $sql;
        foreach ($binds as $name => $value) {
            $formattedValue = $value;

            if (\is_object($value)) {
                $formattedValue = (string)$value;
            }

            if (\is_string($formattedValue)) {
                $formattedValue = sprintf("'%s'", $formattedValue);
            }
            $finalSql = str_replace(":$name", $formattedValue, $finalSql);
        }

        return $finalSql;
    }