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

13

在Phalcon中,是否可以从查询构建器实例中提取原始的SQL查询语句?类似于这样:

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

$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();
6个回答

20

通过试误,以下代码似乎运行良好。如果有更好的方法,请有人确认一下。

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

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

编辑:自2.0.3版本起,您可以非常简单地完成此操作,请参见评论获取完整详情:

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

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

更多内容可以阅读此处

1
以下是常见的解决方案:
$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] => 
)

So, this simple code might be useful:

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

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

这是我用于调试的简单函数。


0
如果您正在使用查询构建器,则可以像下面这样使用,然后根据Phalcon 3.4.4版本,getPhql函数可以实现目的。

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


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