我维护的一个旧的Cake库存应用程序中的一些遗留代码目前遇到了一个问题。该应用程序包含库存项目,这些项目应该只被与项目位于同一位置的用户看到。因此,我们有这些项目,沿着一些其他模型。扩展BaseTable。这实际上获取了登录用户能够使用getUserLocationIds查看库存项目的位置的ID(),然后将输出附加到beforeFindRule()上的查询,以筛选出用户不应看到的项目:
<?php
class BaseTable extends Cake\ORM\Table
{
public function beforeFind(Event $event, Query $query, ArrayObject $options)
{
parent::beforeFind($event, $query, $options);
$repositoryTable = $query->getRepository()->getAlias();
$loacationIds = Cake\ORM\TableRegistry::getTableLocator()
->get("Locations")
->getUserLocationIds();
$query->andWhere([$repositoryTable . ".location_id IN " => $locationIds]);
}
}
以上代码在生产中已经运行了很多年。虽然现在我们得到了一个用户,但他不能看到他们位置上的现有项目,因为软件将该项目分配到了他们无权访问的另一个位置。他们假定该项目不在系统中,并使用相同的id_number和client_id创建另一个项目。
ItemsTable应使用下面列出的buildRule()限制此操作:
<?php
class ItemsTable extends BaseTable
{
public function buildRules(Cake\ORM\RulesChecker $rules): Cake\ORM\RulesChecker
{
$rules->add($rules->isUnique(['id_number', 'client_id'], 'The Number you selected is in use, please use another'));
return $rules;
}
}
但是,构建规则无法限制此重复项,因为第一个代码片段中beforeFind()中提到的代码导致isUnique()仅检查getUserLocationIds()返回的条目。
我想知道如何使beforeFind()中的逻辑不应用于buildRules()中的函数调用?或者是否有更好的方法来做到这一点?
附加问题:我应该在MySQL和CakePHP中验证这个规则吗?在CakePHP应用程序中验证这类事情的最佳实践是什么?
谢谢你!
编辑:我还不能100%确定,但是经过进一步的检查,这个问题可能与CakePHP中的一个bug有关,而不是代码的实现。
1条答案
按热度按时间yh2wf1be1#
我不会说这是一个bug,在我看来它更像是预期的行为,毕竟
beforeFind
是影响所有ORM查询的。如果该规则忽略
beforeFind
修改(这将是一件有点复杂的事情),那么这将导致另一端的许多问题,即对于那些情况下,人们 * 希望 * 查询修改应用。恕我直言,目前最干净的方法是,例如,使用一个自定义查找器来应用位置限制,然后在希望使用它的地方显式使用它,或者使用一个自定义/扩展规则,在这里您可以传递查询选项,您的
beforeFind
回调可以评估这些选项,以使过滤器可选。就核心而言,如果规则能够接受允许修改查询的回调,这可能会有所帮助。
是的,你还应该考虑在数据库表中添加适当的唯一索引,这样即使花哨的反馈应用程序规则失败了,也能确保数据的完整性。