Php 有没有办法在Phalcon中使用新的PostgreSQL 9.3 JSON操作符?
我正在寻找一种方法来利用新的技术 一个简单的表格来演示:Php 有没有办法在Phalcon中使用新的PostgreSQL 9.3 JSON操作符?,php,phalcon,postgresql-9.3,Php,Phalcon,Postgresql 9.3,我正在寻找一种方法来利用新的技术 一个简单的表格来演示: CREATE TABLE "user" ( id_user serial NOT NULL, data json, CONSTRAINT pk_user PRIMARY KEY (id_user) ) 以及在psql中运行良好的查询: select * from "user" where data->>'email' = 'john@example.com'; 但是,当针对以下对象使用时: 它会产生语法错误:
CREATE TABLE "user"
(
id_user serial NOT NULL,
data json,
CONSTRAINT pk_user PRIMARY KEY (id_user)
)
以及在psql
中运行良好的查询:
select * from "user" where data->>'email' = 'john@example.com';
但是,当针对以下对象使用时:
它会产生语法错误:
ERROR: Syntax error, unexpected token >, near to '>'email' = :email:', when parsing: SELECT [Pht\Cli\Model\UserModel].* FROM [Pht\Cli\Model\UserModel] WHERE data->>'email' = :email:
我猜这和不能处理语法有关。但问题仍然存在:如何将JSON查询与Phalcon一起使用
我尝试将JSON语法包装成:
但它似乎只是为了更新/插入:
ERROR: Conditions must be string
我总是可以编写一个原始查询,但这显然不是正确的方法。另外,最好在
Model::find
和Model::findAll
中提供语法,看看是否有一个底层函数实现了->
操作符,并改用它。您可以在->
的oprname
中查找pg\u操作符
;您将看到oprcode
标识底层函数。对于不同的数据类型组合,可能有多个条目,因此您必须选择正确的条目。如果需要,您可以在pg_type
上加入oprift
和opright
以获取类型名称
那会给你一个临时的解决办法。更好的方法是避免尝试在框架中解析SQL,或修复其解析器以处理复杂的运算符。在深入研究源代码和阅读论坛后,我发现了一个基于SQL的非常好的解决方法。基本思想是使用自定义数据库函数语法,在执行查询之前捕获并解析一个特殊的虚拟函数:
UserModel::query()->where("PG_JSON_PATH(\"data->>'email'\") = :email:");
为了实现这一点,我们需要一个专门的Postgres适配器(下面的一个适配器也使用这种方法来潜入原始帖子中的子查询):
目前,您可以使用内置的postgres功能:
根据Craig answer,您可以在Postgres上执行此查询,以查找您要查找的操作员以及在查询中使用的等效代码: 例如:
从pg_运算符中选择oprcode,其中oprname='->'代码>
你会得到很多结果,使用合适的方法
谢谢,Phalcon是用C编写的,所有查询在内部都被翻译成一种叫做PHQL的特殊语言,PHQL本身就是用lemon实现的。我翻遍了源代码,没有迹象表明qurrent PHQL实现可以支持->
符号。当我有空余时间时,我会尽力的。
ERROR: Conditions must be string
UserModel::query()->where("PG_JSON_PATH(\"data->>'email'\") = :email:");
class Postgresql93 extends \Phalcon\Db\Adapter\Pdo\Postgresql
{
public function query($sqlStatement, $bindParams = null, $bindTypes = null)
{
$sqlStatement = $this->handle93syntax($sqlStatement);
return parent::query($sqlStatement, $bindParams, $bindTypes);
}
private function handle93syntax($sqlStatement)
{
$specials = join('|', ['SUB_QUERY', 'PG_JSON_PATH']);
$pattern = "/($specials)[\\s]*\\([\\s]*\\'(.*)\\'[\\s]*\\)/";
$sqlStatement = preg_replace_callback(
$pattern,
function(array $matches){
$content = str_replace("''", "'", $matches[2]);
return $content;
},
$sqlStatement
);
return $sqlStatement;
}
}
UserModel::query()->where("json_extract_path_text(data, 'email') = :email:");