在遗留项目中,我们遇到的问题是,如果开发人员在查询条件中忘记了project_id,则会显示所有项目的行 - 而不是他们要查看的单个项目。例如,对于"评论":
comments [id, project_id, message ]
如果您忘记按project_id过滤,您会看到所有项目。这是通过测试捕获的,有时不是,但我宁愿做一个预防 - 开发应该直接看到"错误/空"!
为了解决这个问题,产品经理坚持要求提供单独的评论表,如下所示:
project1_comments [id,message]
project2_comments [id,message]
如果您忘记了项目/表格名称,如果某些内容仍然通过测试并已部署,您将不会得到任何错误或错误。
然而,困难在于相关表格。示例"文件"链接到"评论":
files [ id, comment_id, path ]
3, 1, files/foo/bar
project1_comments
id | message
1 | Hello World
project2_comments
id | message
1 | Bye World
然后每个项目变成一个数据库,这似乎有点过分了。
另一种可能性,如何在Comments模型上添加一个Behavior以确保任何find / select查询都包含外键,例如 - project_id?
非常感谢提前。
答案 0 :(得分:0)
在遗留项目中,如果开发人员在查询条件中忘记了project_id,我们会遇到问题
CakePHP根据您为表定义的关联生成连接条件。当您使用 contains 时,它们自动,并且开发人员不太可能在CakePHP中犯这样的错误。
不要这样做。对我来说似乎是一个非常糟糕的主意。为了解决这个问题,产品经理坚持要求提供单独的评论表,如下所示:
另一种可能性,如何在Comments模型上添加一个Behavior以确保任何find / select查询都包含外键,例如 - project_id?
最简单的解决方案是禁止Comments
表上的所有直接查询。
class Comments extends Table {
public function find($type = 'all', $options = [])
{
throw new \Cake\Network\Exception\ForbiddenException('Comments can not be used directly');
}
}
之后只允许Comments
通过关联阅读(关联总是有有效的加入条件),但在此之前要三思而后行,因为我没有看到这种限制带来任何好处。
您无法轻松地将Comments
上的直接查询限制为仅包含 where 子句中product_id
的查询。问题是其中子句是表达式树,您必须遍历树并检查所有不同类型的表达式。这很痛苦。
我要做的是限制Comments
,以便product_id
必须作为选项传递给查找程序。
$records = $Comments->find('all', ['product_id'=>$product_id])->all();
以上操作是将$product_id
作为表的默认findAll
方法的选项传递。我们可以覆盖这些方法并强制product_id
作为所有直接评论查询的必需选项。
public function findAll(Query $query, array $options)
{
$product_id = Hash::get($options, 'product_id');
if (!$product_id) {
throw new ForbiddenException('product_id is required');
}
return $query->where(['product_id' => $product_id]);
}
我没有看到通过行为执行上述操作的简单方法,因为 where 子句在执行行为时仅包含表达式。