【Yii2】关于 Yii2 权限控制里的 bug

icy2003 程序 2020-12-27 08:47:37 219 0条
  • 这确实是 Yii2 的 bug,是的,是的,是的
  • 我:好像玩梗过度。别人:你是不是觉得自己很幽默?

考试挂了一门,不过问题不大

这段空闲时间稍微写了一点东西,其中涉及到 Yii2 权限控制修改角色(或者权限、规则等),虽然问题的解决过程不复杂,但是这种隐藏的彩蛋见到的话是真的有种被人秀的感觉,所以还是发出来

下面是一段用来更新“角色名”的代码:

$auth = Yii::$app->authManager;
$role = $auth->getRole($name);
$role->name =  $newName;
$auth->update($name, $role);

我用到的 authManager 是数据库的,update 方法最终会调用 yii\rbac\DbManager 里的 updateItem 方法,以下为关键代码:

if ($item->name !== $name && !$this->supportsCascadeUpdate()) {
    $this->db->createCommand()
        ->update($this->itemChildTable, ['parent' => $item->name], ['parent' => $name])
        ->execute();
    $this->db->createCommand()
        ->update($this->itemChildTable, ['child' => $item->name], ['child' => $name])
        ->execute();
    $this->db->createCommand()
        ->update($this->assignmentTable, ['item_name' => $item->name], ['item_name' => $name])
        ->execute();
}

意思就是说,如果新的名字不等于旧的名字,并且“supportsCascadeUpdate”,那么就更新子表

supportsCascadeUpdate 的官方 API 文档介绍是“返回一个值,指示数据库是否支持级联更新和删除。对于 SQLite 数据库,默认实现将返回 false,对于所有其他数据库,则返回 true”(其实自己看代码也看得懂)

其他数据库,那就是包括 Mysql 喽~

那么就是说,上面代码的意思是,“当改了名字,并且是 Mysql 数据库”的时候,就更新

为了把重点突出,我特地改了“不”的颜色

看到这里我傻了,我相信看到这里的你们也傻了,这逻辑不通啊,于是我用 Xdebug 调试,结果就是上面解释的那样

大史(《我的三体》中角色)曾说过:“事出反常必有妖”(实际上是纪晓岚说的)

肯定还是我的理解有问题,反复看了好几次官方 API 后我发现了“是否支持级联更新和删除……级联更新和删除……级联”

龙珠超 BGM 起~哦,不对,不是那个吉连!

实际上,那句代码的含义应该是指,如果改了名,并且数据库不支持级联,那么才执行之后的代码,之后代码就是更新子表的操作

“级联”在这里简而言之就是“外键”,整段代码再翻译过来就是“如果数据库不支持自动改名,才手动改名”

MyISAM 不支持外键,级联自然就不存在,我习惯是用 InnoDB 的,至于为什么变成了 MyISAM,那是因为默认配置的问题

default-storage-engine=InnoDB
# skip-innodb

Mysql 配置改成这两个,再看看最终创建的表是不是 InnoDB,是的话,问题就解决了

问题的最终原因除了我自己没看清外,我觉得 supportsCascadeUpdate 方法本身就有问题,是简单通过字符串匹配去检测“是否支持级联”的,算是一个小小的 bug 吧,最后……

现在谁还在用 MyISAM 啊!好吧,我是被迫的……

标签: yii2

非特殊说明,本博所有文章均为博主原创。