如何使用 CakePHP3 ORM 获取字符串格式的 where 子句?

how to get the where clause in string format using CakePHP3 ORM?

在 CakePHP3 中,有一个 ORM 可以帮助构建查询。

documentation可以看出

$query = $articles->find(); // build a query that has not run yet
$query->where(['id' => 1]); // Return the same query object

所以在这种情况下,我想要字符串

WHERE `articles`.`id` = 1

经过多次谷歌搜索,我发现有一种方法to return just the where clause of a query object

$query->where(['id' => 1])->clause('where'); // Return the where clause in the form of a QueryExpression

更多的谷歌搜索让我找到了如何get the QueryExpression to spit out string representation

$query->where(['id' => 1])->clause('where')->sql($valueBinder); // Return the where clause in string format

这是我的问题。我不知道 $valueBinder 应该是什么样子。不知道怎么初始化。

我也很高兴不使用 ValueBinder,只要我可以使用 CakePHP 3 ORM 和正确的 SQL 方言获得字符串格式的 where 子句。请假设我使用的是 MySQL.

请指教

编辑

我尝试使用 $query->valueBinder() 作为 $valueBinder

它是空的,不包含关联的 c:0 到值 1

如果你愿意,你可以选择省略这个参数。请参阅 http://api.cakephp.org/3.0/class-Cake.Database.Query.html#_sql

另外,可以使用Query成员函数traverse($visitor, $parts)来隔离where子句。 $visitor 是一个带有值和子句的函数。您定义 $visitor 的行为。 $parts 是子句名称的数组。我建议将 array('where') 传递给这个参数。

我的解决方法是将条件存储为 json 字符串格式。

用同样的例子,我做的是

$data['conditions'] = json_encode(['Articles.id' => 1]); // encode into JSON string
$this->DynamicRules->patchEntity($dynamicRule, $data); // use in edit action of DynamicRulesController

然后当我需要重用条件时,我会这样做:

$articlesTable = TableRegistry::get('Articles');
$query = $articlesTable->find(); // new query for Articles

$rule = json_decode($dynamicRule->conditions, true); // get back the conditions in associative array format
$query->where($rule); // re-assign the conditions back

这让我得到了我最终想要的东西。

要直接回答您的问题,您可以通过以下方式获得任何子句的 SQL:

$binder = new \Cake\ORM\ValueBinder();
$query->clause('where')->sql($binder);

这将 return SQL 与正确的占位符,而不是要使用的值。这些值存在于 $binder 变量中并用于语句对象。

如我所见,您只想保留 where 子句的内部结构以将其传递给不同请求中的另一个查询。您的解决方案很好,但我想补充一点,您还可以根据现有查询对完整条件树进行编码:

$where = serialize($query->clause('where'));
$anotherQuery->where(unserialize($where)); // A query in another request

在任何情况下,您都需要小心反序列化的内容,因为直接从用户输入中获取它肯定会导致安全问题。