如何确保开发人员在CakePHP中使用外键进行过滤

时间:2018-01-03 15:42:37

标签: cakephp cakephp-3.0

在遗留项目中,我们遇到的问题是,如果开发人员在查询条件中忘记了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?

非常感谢提前。

1 个答案:

答案 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 子句在执行行为时仅包含表达式。