社区,
我目前面临基于数据源表达式构建器的可包含行为设置条件的问题。我正在使用带有PostgreSQL数据库的CakePHP 2.6.2。
到目前为止有效:
我写了一个行为,动态地为 find - 操作添加条件,以根据特权表限制结果。我使用子查询与蛋糕提供的 buildstatement()和表达式()函数。我从CakeBook上看了这篇文章:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
这是一个简单的代码片段,实际上是两个OR语句:
$conditionsSubQueryRecord = array(
'Privilege.objecttable' => $model->table,
'Privilege.objectid = '.$model->alias.'.'.$model->primaryKey,
'Privilege.read' => true,
'Privilege.id' => $this->recordPermissions
);
$dsPrivilege = $this->privilegeModel->getDataSource();
$subQueryRecordPrivs = $dsPrivilege->buildStatement(
array(
'fields' => array('"'.$this->privilegeModel->alias.'"."id"'),
'table' => $dsPrivilege->fullTableName($this->privilegeModel),
'alias' => $this->privilegeModel->alias,
'limit' => null,
'offset' => null,
'joins' => array(),
'conditions' => $conditionsSubQueryRecord,
'order' => null,
'group' => null
),
$this->privilegeModel
);
$subQueryRecordPrivs = ' EXISTS (' . $subQueryRecordPrivs . ') ';
$subQueryRecordPrivsExpression = $dsPrivilege->expression($subQueryRecordPrivs);
我正在将我的条件数组中的语句添加到我的行为beforeFind() - hook中。到目前为止,这一切都很顺利。添加条件,结果被过滤。
我所包含的模型会忽略这些条件:
我现在的问题是在包含的模型上使用这个条件。我写了一个递归算法,沿着所有包含的模型走,如果模型作为我的行为,我将相同的条件附加到其条件数组。但是当我执行搜索时,条件在包含的模型上被忽略,并且仅附加到主模型。
这是我正在执行的完整条件字符串:
array(
'conditions' => array(
'Requestinstance.id' => (int) 4,
(int) 0 => object(stdClass) {
type => 'expression'
value => ' EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'requestinstances' AND "Privilege"."objectid" = "Requestinstance"."id" AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" = (8)) OR EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'requestinstances' AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" IN (7, 13, 6, 9, 10, 12) AND "Privilege"."objectid" IS NULL) '
}
),
'fields' => null,
'joins' => array(),
'limit' => (int) 1,
'offset' => null,
'order' => array(
(int) 0 => null
),
'page' => (int) 1,
'group' => null,
'callbacks' => true,
'contain' => array(
'Requesttype' => array(
'Steptype' => array(
'order' => array(
(int) 0 => 'RequesttypesSteptype.phase ASC'
),
'conditions' => object(stdClass) {
type => 'expression'
value => ' EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'steptypes' AND "Privilege"."objectid" = "Steptype"."id" AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" = (8)) OR EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'steptypes' AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" IN (7, 13, 6, 9, 10, 12) AND "Privilege"."objectid" IS NULL) '
}
),
(int) 0 => 'RequesttypesSteptype',
'conditions' => object(stdClass) {
type => 'expression'
value => ' EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'requesttypes' AND "Privilege"."objectid" = "Requesttype"."id" AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" = (8)) OR EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS "Privilege" WHERE "Privilege"."objecttable" = 'requesttypes' AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" IN (7, 13, 6, 9, 10, 12) AND "Privilege"."objectid" IS NULL) '
}
),
'Stepinstance' => array(
(int) 0 => 'Steptype',
(int) 1 => 'Stepdatainstance',
(int) 2 => 'Sectioninstance'
),
'Requestdatainstance' => array(),
'Taskinstance' => array()
),
'recursive' => (int) 2
)
如您所见,条件已正确添加到某些包含的模型中。但是,执行的SQL查询,即“Steptype”-Model,是在没有条件的情况下生成的:
SELECT "Steptype"."id" AS "Steptype__id", "Steptype"."name" AS "Steptype__name", "Steptype"."description" AS "Steptype__description", "Steptype"."subscribe" AS "Steptype__subscribe", "RequesttypesSteptype"."id" AS "RequesttypesSteptype__id", "RequesttypesSteptype"."phase" AS "RequesttypesSteptype__phase", "RequesttypesSteptype"."endsphase" AS "RequesttypesSteptype__endsphase", "RequesttypesSteptype"."endsrequest" AS "RequesttypesSteptype__endsrequest", "RequesttypesSteptype"."usertype_id" AS "RequesttypesSteptype__usertype_id", "RequesttypesSteptype"."requesttype_id" AS "RequesttypesSteptype__requesttype_id", "RequesttypesSteptype"."steptype_id" AS "RequesttypesSteptype__steptype_id" FROM "core"."steptypes" AS "Steptype" JOIN "core"."requesttypes_steptypes" AS "RequesttypesSteptype" ON ("RequesttypesSteptype"."requesttype_id" = 6 AND "RequesttypesSteptype"."steptype_id" = "Steptype"."id") ORDER BY "RequesttypesSteptype"."phase" ASC
直接使用buildStatement不起作用
我还尝试直接使用语句本身,而不从中构建表达式。这实际上创建了我想要的SQL查询,但是没有正确地在FROM子句中添加表别名的引号,因此导致postgreSQL抛出错误:
SELECT "Requestinstance"."id" AS "Requestinstance__id", "Requestinstance"."user_id" AS "Requestinstance__user_id", "Requestinstance"."created" AS "Requestinstance__created", "Requestinstance"."requesttype_id" AS "Requestinstance__requesttype_id", "Requestinstance"."currentphase" AS "Requestinstance__currentphase", "Requestinstance"."selfsolving" AS "Requestinstance__selfsolving", "User"."username" AS "User__username", "User"."id" AS "User__id", "User"."company_id" AS "User__company_id", "User"."usertype_id" AS "User__usertype_id", "Requesttype"."id" AS "Requesttype__id", "Requesttype"."name" AS "Requesttype__name", "Requesttype"."subtitle" AS "Requesttype__subtitle", "Requesttype"."description" AS "Requesttype__description", "Requesttype"."order" AS "Requesttype__order", "Requesttype"."selfsolving" AS "Requesttype__selfsolving" FROM "core"."requestinstances" AS "Requestinstance" LEFT JOIN "core"."users" AS "User" ON ("Requestinstance"."user_id" = "User"."id") LEFT JOIN "core"."requesttypes" AS "Requesttype" ON ("Requestinstance"."requesttype_id" = "Requesttype"."id") WHERE EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS Privilege WHERE "Privilege"."objecttable" = 'requestinstances' AND "Privilege"."objectid" = "Requestinstance"."id" AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" = (8)) OR EXISTS (SELECT "Privilege"."id" FROM "core"."privileges" AS Privilege WHERE "Privilege"."objecttable" = 'requestinstances' AND "Privilege"."read" = 'TRUE' AND "Privilege"."id" IN (7, 13, 6, 9, 10, 12) AND "Privilege"."objectid" IS NULL) LIMIT 1
在构建语句时手动将引号添加到别名字符串也无济于事,因为框架会删除引号。
最后我的问题:
有人知道,如果可包含行为支持表达式吗?我已经深入研究了DboSource,PdoSource和Postgresql-datasource,但在这里找不到任何错误。 Containable行为看起来也很简单。我在这里做错了吗?
还是有另一种方式可以取得我想要的东西吗?
我很高兴在这件事上有任何帮助! 提前谢谢!
答案 0 :(得分:0)
我终于明白了!
正式回答这个问题:
是的,可包含的行为确实支持表达式语法!
我的问题在于处理顺序:框架处理配置顺序的行为,我意外地在我的自定义行为之前加载了包含,这就是为什么它从未收到我修改过的条件......
使用正确的顺序,可操作的条件字符串被可包含的行为处理得很好。
为了绝对确定行为顺序,我将行为加载移动到了AppModels __construct()方法:
// unload any configured Containable behavior
if($this->Behaviors->loaded('Containable')) {
$this->Behaviors->unload('Containable');
}
// load the PrivilegeItem behavior
if($this->alias !== 'Privilege') {
$this->Behaviors->load('PrivilegeItem');
}
// and finally (re-)attach the Containable behavior
$this->Behaviors->load('Containable');
也许它可以帮助其他人避免两天的调试头痛...