在Phalcon中,是否可以从查询构建器实例中提取原始的SQL查询语句?类似于这样:
$queryBuilder = new Phalcon\Mvc\Model\Query\Builder();
$queryBuilder
->from(…)
->where(…);
$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();
在Phalcon中,是否可以从查询构建器实例中提取原始的SQL查询语句?类似于这样:
$queryBuilder = new Phalcon\Mvc\Model\Query\Builder();
$queryBuilder
->from(…)
->where(…);
$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();
通过试误,以下代码似乎运行良好。如果有更好的方法,请有人确认一下。
$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()
$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);
}
$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;
}
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;
}
}
这是我用于调试的简单函数。
getPhql
函数可以实现目的。
$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…)->getQuery();
$queryBuilder->getPhql();