【问题标题】:How to ensure developers filter by a foreign key in CakePHP如何确保开发人员在 CakePHP 中通过外键过滤
【发布时间】:2018-01-03 15:42:36
【问题描述】:

在旧项目中,如果开发人员忘记了查询条件中的 project_id,则会显示所有项目的行,而不是他们应该看到的单个项目。例如对于“评论”:

 comments [id, project_id, message ]

如果您忘记按 project_id 过滤,您会看到所有项目。这被测试发现了,有时没有,但我宁愿做一个预防 - 开发人员应该直接看到“错误/空”!

为了解决这个问题,产品经理坚持为 cmets 使用单独的表,如下所示:

 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 以确保任何查找/选择查询确实包含外键,例如 - project_id?

非常感谢。

【问题讨论】:

    标签: cakephp cakephp-3.0


    【解决方案1】:

    在遗留项目中,如果开发人员忘记查询条件中的 project_id,我们会遇到问题

    CakePHP 根据您为表定义的关联生成连接条件。当您使用 contains 时,它们是自动的,开发人员不太可能在使用 CakePHP 时犯这样的错误。

    为了解决这个问题,产品经理坚持为 cmets 使用单独的表,如下所示:

    不要这样做。对我来说似乎是一个非常糟糕的主意。

    另一种可能性,如何在 Comments 模型上添加 Behavior 以确保任何查找/选择查询确实包含外键,例如 - 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 的查询。问题是 where 子句是一个表达式树,您必须遍历树并检查所有不同类型的表达式。这很痛苦。

    我要做的是限制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 子句在执行行为时只包含表达式。

    【讨论】:

      猜你喜欢
      • 2022-12-06
      • 2016-07-19
      • 2019-06-18
      • 2014-08-13
      • 1970-01-01
      • 2014-08-06
      • 2019-07-23
      • 2013-02-02
      • 1970-01-01
      相关资源
      最近更新 更多