从 Phalcon 查询生成器获取原始 sql

Posted

技术标签:

【中文标题】从 Phalcon 查询生成器获取原始 sql【英文标题】:Get raw sql from Phalcon query builder 【发布时间】:2014-02-15 20:05:05 【问题描述】:

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

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

$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();

【问题讨论】:

【参考方案1】:

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

根据文档,您可以通过这种方式获得生成的 sql 查询。

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

【讨论】:

【参考方案2】:

通过错误和尝试,以下似乎有效。如果有人能确认是否有更好的方法,那就太好了。

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

【讨论】:

【参考方案3】:
$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

【讨论】:

【参考方案4】:

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


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

【讨论】:

【参考方案5】:
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;
    

我用来调试的简单函数。

【讨论】:

【参考方案6】:

以下是常见的解决方案:

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

【讨论】:

以上是关于从 Phalcon 查询生成器获取原始 sql的主要内容,如果未能解决你的问题,请参考以下文章

如何让查询生成器将其原始 SQL 查询输出为字符串?

如何让查询生成器将其原始 SQL 查询输出为字符串?

我如何将 SQL 原始查询重写为 Laravel 查询生成器

在 CodeIgniter 1.7 中获取原始 SQL 查询

获取由 sequelize.js 生成的原始查询 [重复]

使用原始 SQL 查询生成表,并希望在 Django 中将这些表用作 ORM