CakePHP ORM:在具有非标准关联的同一个表上使用联接进行查询

CakePHP ORM:在具有非标准关联的同一个表上使用联接进行查询,php,cakephp,orm,query-builder,cakephp-3.x,Php,Cakephp,Orm,Query Builder,Cakephp 3.x,我有一个非常特殊的用例,我无法用ORM找到一个干净的解决方案。我搜索了很多,也许我的数据库模型不正确,我不确定 我使用CakePHP3.8.11 因此,我有一个表“MaintenanceTypes”,其中包含3个重要字段:id、名称和周期。周期性(以天为单位)表示“每(例如)30天进行一次维护” 周期性如7(周)、30(月)、90(三个月)等 我还有一个表“Operations”,它们是属于“MaintenanceType”的小单元测试(字段是id、name、MaintenanceType\u

我有一个非常特殊的用例,我无法用ORM找到一个干净的解决方案。我搜索了很多,也许我的数据库模型不正确,我不确定

我使用CakePHP3.8.11

因此,我有一个表“MaintenanceTypes”,其中包含3个重要字段:id、名称和周期。周期性(以天为单位)表示“每(例如)30天进行一次维护”

周期性如7(周)、30(月)、90(三个月)等

我还有一个表“Operations”,它们是属于“MaintenanceType”的小单元测试(字段是id、name、MaintenanceType\u id)

这种情况的特殊之处在于,作为一项业务规则,属于周期为7天的维护类型的操作被“包括”在周期更大的每个维护类型中;这意味着每三个月,你都应该做与该三个月直接相关的每一个手术,但也要做与该月、该周等相关的每一个手术

在原始SQL中,它很简单:微微一笑:

mt_ref是参考维护类型,mt_inc是包含的维护类型(周期性较小),最后是属于找到的任何维护类型的所有操作

选择机器参考id、机器参考名称、机器参考周期,
mt_公司名称,mt_公司周期,o.name
来自维护类型mt\U ref
左连接维护类型mt公司

在(mt_inc.periodicy上,如果您需要查询生成器实例,那么这里几乎有两个简单的选项,即使用与自定义条件的关联或手动联接

自定义关联条件 通过关联,您可能会使用禁用的外键和自定义条件与
MaintenanceTypes
进行自我关联,例如在
MaintenanceTypesTable
类中:

$this
->有许多('MaintenanceTypesInc')
->setClassName('MaintenanceTypes')
->setForeignKey(错误)
->设置条件(函数)(
\Cake\Database\Expression\QueryExpression$exp,
\蛋糕\ORM\Query$Query
) {
返回$exp->lte(
$query->identifier('MaintenanceTypesInc.periodicity'),
$query->identifier('MaintenanceTypes.periodicity')
);
});
禁用外键将阻止ORM在加入关联时创建默认的
A.fk=B.fk
条件。应注意,禁用外键时不能包含
hasMany
关联,只能将其加入!您可以使用
hasOne
甚至
belongsTo
associ相反,这将是一个谎言,因为你在这里没有1:1的关系(至少据我所知)

还请注意,您不必对条件的所有表达式使用回调,您可以使用手动实例化的标识符表达式将条件作为
key=>value
数组传递,甚至可以作为简单字符串传递(但是,使用自动标识符引用时将无法识别后者):

->setConditions([
'维护类型Sinc.周期性选择([
“MaintenanceTypes.id”、“MaintenanceTypes.name”、“MaintenanceTypes.Periodicy”,
'mt_inc_name'=>'MaintenanceTypesInc.name','mt_inc_Periodicy'=>'MaintenanceTypesInc.Periodicy',
'op_name'=>'Operations.name',
])
如果不希望每次都选择所有字段,请使用下面的手动连接示例中的自定义查找器

手动连接 使用手动联接可以让您完全自由,使用查询生成器
*Join()
方法,您可以创建任何您喜欢的联接,并且不必使用可能的关联解决方法

您可以将它们添加到自定义查找器中以获得适当的可重用性,在您的
MaintenanceTypesTable
类中可能会出现如下情况:

找到的公共函数包含udedMaintenance类型(\Cake\ORM\Query$Query,array$options)
{
返回$query
->选择(/*…*/)
->左连接(
['MaintenanceTypesInc'=>'MaintenanceTypes'],
作用(
\Cake\Database\Expression\QueryExpression$exp,
\蛋糕\ORM\Query$Query
) {
返回$exp->lte(
$query->identifier('MaintenanceTypesInc.periodicity'),
$query->identifier('MaintenanceTypes.periodicity')
);
}
)
->左连接(
[“操作”=>“操作”],
作用(
\Cake\Database\Expression\QueryExpression$exp,
\蛋糕\ORM\Query$Query
) {
返回$exp->equalFields(
“操作.维护类型\u id”,
“MaintenanceTypesInc.id”
);
}
);
}
然后,您只需在任何需要的地方使用finder,如下所示:

$query=$maintenanceTypesTable
->查找('withIncludedMaintenanceTypes');
请注意,就像在关联示例中一样,您也可以对自定义联接使用字符串或数组条件

另见

如果您需要查询生成器实例,那么这里几乎有两个简单的选项,即使用与自定义条件的关联或手动联接

自定义关联条件 通过关联,您可能会使用禁用的外键和自定义条件与
MaintenanceTypes
进行自我关联,例如在
MaintenanceTypesTable
类中:

$this
->有许多('MaintenanceTypesInc')
->setClassName('MaintenanceTypes')
->设置外键(