CakePHP 3 与按位表达式有很多关联
CakePHP 3 hasMany association with bitwise expression
我有两个表,AclGroups 和 AclPermissions,我想在它们之间创建一个 hasMany 关系,即 AclGroups 有很多 AclPermissions。
确定一个组是否拥有给定权限的条件是在单个位检查中完成的。这就是我想要做的:
SELECT
*
FROM
acl_groups
JOIN
acl_permissions ON acl_permissions.permission & acl_groups.permission != 0
在 AclGroupsTable
中,我尝试了以下方法:
$this->hasMany('AclPermissions', [
'className' => 'AclPermissions',
'foreignKey' => 'permission',
'conditions' => [
'AclPermissions.permission & AclGroups.permission !=' => 0
]
]);
但这只是给了我
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'aclgroups.permission' in 'where clause'
在我的控制器中我这样做:
$this->AclGroups->find('all')->contain(['AclPermissions']);
我想真正的问题是:有没有办法可以更改获取关联记录的查询中 ON 子句的条件
如评论中所述,使用 contain()
.[=21= 时,hasMany
关联(以及 belongsToMany
关联)的记录将始终在单独的查询中检索]
如果您需要使用此类关联创建连接,则必须明确使用连接的相应功能,例如 leftJoinWith()
:
$this->AclGroups->find('all')->leftJoinWith('AclPermissions');
这将创建一个类似于您显示的查询。但是它也会使用配置的外键生成默认条件,您必须禁用外键以避免这种情况,例如:
$this->hasMany('AclPermissions', [
'foreignKey' => false, // << like this
// ...
]);
鉴于关联条件不适用于 contain()
(并且禁用外键将使其更无法用于此目的),您可能希望为加入目的创建一个单独的关联,或使用 "lower level" 连接方法,您可以在其中手动指定所有条件(例如,您可以将其放入自定义查找器中以保持代码干燥):
$query = $this->AclGroups
->find('all')
->join([
'table' => 'acl_permissions',
'alias' => 'AclPermissions',
'type' => 'LEFT',
'conditions' => [
'AclPermissions.permission & AclGroups.permission != :permission'
]
])
->bind(':permission', 0, 'integer');
请注意,值在此处被显式绑定以确保使用正确的类型,因为它无法从非标准的左手值(实际上并不包含 SQL 片段 - 您可能想要研究使用表达式)。
另见
我有两个表,AclGroups 和 AclPermissions,我想在它们之间创建一个 hasMany 关系,即 AclGroups 有很多 AclPermissions。
确定一个组是否拥有给定权限的条件是在单个位检查中完成的。这就是我想要做的:
SELECT
*
FROM
acl_groups
JOIN
acl_permissions ON acl_permissions.permission & acl_groups.permission != 0
在 AclGroupsTable
中,我尝试了以下方法:
$this->hasMany('AclPermissions', [
'className' => 'AclPermissions',
'foreignKey' => 'permission',
'conditions' => [
'AclPermissions.permission & AclGroups.permission !=' => 0
]
]);
但这只是给了我
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'aclgroups.permission' in 'where clause'
在我的控制器中我这样做:
$this->AclGroups->find('all')->contain(['AclPermissions']);
我想真正的问题是:有没有办法可以更改获取关联记录的查询中 ON 子句的条件
如评论中所述,使用 contain()
.[=21= 时,hasMany
关联(以及 belongsToMany
关联)的记录将始终在单独的查询中检索]
如果您需要使用此类关联创建连接,则必须明确使用连接的相应功能,例如 leftJoinWith()
:
$this->AclGroups->find('all')->leftJoinWith('AclPermissions');
这将创建一个类似于您显示的查询。但是它也会使用配置的外键生成默认条件,您必须禁用外键以避免这种情况,例如:
$this->hasMany('AclPermissions', [
'foreignKey' => false, // << like this
// ...
]);
鉴于关联条件不适用于 contain()
(并且禁用外键将使其更无法用于此目的),您可能希望为加入目的创建一个单独的关联,或使用 "lower level" 连接方法,您可以在其中手动指定所有条件(例如,您可以将其放入自定义查找器中以保持代码干燥):
$query = $this->AclGroups
->find('all')
->join([
'table' => 'acl_permissions',
'alias' => 'AclPermissions',
'type' => 'LEFT',
'conditions' => [
'AclPermissions.permission & AclGroups.permission != :permission'
]
])
->bind(':permission', 0, 'integer');
请注意,值在此处被显式绑定以确保使用正确的类型,因为它无法从非标准的左手值(实际上并不包含 SQL 片段 - 您可能想要研究使用表达式)。
另见