drodata
问题解决了吗?如果没有,你能把 MyBehavior.php 完整的代码上传上来吗?另外:
发现我不重写beforeAction()方法,就正常,否则行为就失效
这里的“正常”指的是 MyBehavior 能成功拦截某一个禁止访问的 action 吗?"行为就失效“指的也是 MyBehavior 没有拦截住本该禁止访问的 action 吧?换句话说,你标题中的“行为失效”特指的是 behaviors() 中的 MyBehavior.
默认情况下,scenarios() 返回的是一个关系数组,键是模型中所有可用的场景,值是场景对应的 active attributes 列表。active attributes 有两个特点:
- 如 @koko 所说,调用 validate() 时仅会验证 active attributes
- 使用
$model->load() && $model->save()
保存数据时只保存 active attributes;
在你的例子中,把 'age' 从 update 场景中移除意味着 age 不再是 active attribute, 这就是为什么对 age 的修改没有写入数据库的原因。
默认的 scenarios() 过程(以你的例子中声明的规则为例)
scenarios() 会进行两次遍历操作。首先遍历 rules 中声明的规则,把所有可用的场景找出来,并初始化数组,以你的例子中的 rules 为例,值为:
[ 'default' => [], // 框架自带的默认场景 'add' => [], 'update' => [], ]
第二次遍历时,对每个 rule 中声明的 attributes “对号入座”,如果 rule 中不带 'on' 属性,表示该属性所属的规则适用于所有场景(例如
[['age'], 'integer']
), 会将 'age' 追加到所有场景的 active attibutes 列表中;如果指定了场景值,仅在对应的场景下的active attributes 内追加。经过这两次遍历,scenarios() 最终返回的值将是:
[ 'default' => ['age', 'name'], 'add' => ['age', 'name'], 'update' => ['age', 'name'], ]
可以看到, 'age' 在每个场景中都是 active attribute, 这就是为什么在你不重写 scenarios() 的情况下,对 age 的修改也能保存的原因。
了解了这个过程,我的理解是:在大多数情况下,是不需要重写 scenarios() 的,通过配置 rules() 来改变 scenarios() 的返回值,而不是直接手动覆盖 sceanrios(). 覆盖带来的一个明显的弊端是:你的精力被分散到了两个方法内(rules() 和 scenarios()),假设将来你的 info 表又新增了一列,在 rules() 追加新的规则的同时,你还要修改重写后的 scenarios(), 把新增加的列追加进去使其成为 active attribute,否则就会出现新增列的数据无法存入数据库。使用默认的 scenarios() 的话,只需要将精力放在 rules() 上即可。
@xyf90314 可以,而且去掉一个场景后让规则看上去更简洁明了。
默认情况下,scenarios() 返回的是一个关系数组,键是模型中所有可用的场景,值是场景对应的 active attributes 列表。active attributes 有两个特点:
- 如 @koko 所说,调用 validate() 时仅会验证 active attributes
- 使用
$model->load() && $model->save()
保存数据时只保存 active attributes;
在你的例子中,把 'age' 从 update 场景中移除意味着 age 不再是 active attribute, 这就是为什么对 age 的修改没有写入数据库的原因。
默认的 scenarios() 过程(以你的例子中声明的规则为例)
scenarios() 会进行两次遍历操作。首先遍历 rules 中声明的规则,把所有可用的场景找出来,并初始化数组,以你的例子中的 rules 为例,值为:
[ 'default' => [], // 框架自带的默认场景 'add' => [], 'update' => [], ]
第二次遍历时,对每个 rule 中声明的 attributes “对号入座”,如果 rule 中不带 'on' 属性,表示该属性所属的规则适用于所有场景(例如
[['age'], 'integer']
), 会将 'age' 追加到所有场景的 active attibutes 列表中;如果指定了场景值,仅在对应的场景下的active attributes 内追加。经过这两次遍历,scenarios() 最终返回的值将是:
[ 'default' => ['age', 'name'], 'add' => ['age', 'name'], 'update' => ['age', 'name'], ]
可以看到, 'age' 在每个场景中都是 active attribute, 这就是为什么在你不重写 scenarios() 的情况下,对 age 的修改也能保存的原因。
了解了这个过程,我的理解是:在大多数情况下,是不需要重写 scenarios() 的,通过配置 rules() 来改变 scenarios() 的返回值,而不是直接手动覆盖 sceanrios(). 覆盖带来的一个明显的弊端是:你的精力被分散到了两个方法内(rules() 和 scenarios()),假设将来你的 info 表又新增了一列,在 rules() 追加新的规则的同时,你还要修改重写后的 scenarios(), 把新增加的列追加进去使其成为 active attribute,否则就会出现新增列的数据无法存入数据库。使用默认的 scenarios() 的话,只需要将精力放在 rules() 上即可。
一般我在name字段都是存储的节点的形式,如:modules/controll/action
Yii2 RBAC 表格内不是用来存储路由(route, 即你说的“节点”)的。路由的权限判断通过 ACF (Access Control Filter) 实现。
在做项目的时候不可能就用他原原本本的就能满足客户的一些需求,可以在他的源结构中扩展加一些字段……
你说的有道理,前提是你对 Yii2 RBAC 相关知识通读过,有一个整体的、大致的认识。当自己的需求不能实现时,大致有两种可能:一、某个知识点能解决需求,但是该知识点自己不知道;二、需求比较特殊,框架中提供的通用功能满足不了特殊的需求。解决办法是新建一个子类,在子类中进行个性化定制。
如:我有50个权限要检查 YIi会这样去查:
SELECT * FROM data00200 ***
你确定 Yii2 是这样查找的吗?还是 ThinkPHP 是这么查的,所以你觉得 Yii2 也是这么做的?我对 RBAC 了解有限,没有找到这里的出处。
我觉得你走进了一个误区:有意无意地,带着 ThinkPHP 已有的知识结构去理解 Yii2. 框架间的实现原理的确类似,数据结构也可能差别不大,但是实现思路上可能存在差别。
@xjcallen 我看了那段代码,的确如你所说。
你之前举的例子是把 50 个节点(路由)存入数据库,对于我这个不了解 ThinkPHP, 只了解些 Yii2 的人看来,这种做法不好理解,因为使用 Yii::$app->user->can() 时,参数使用的是角色/权限名称而不是路由名称。使用 Access Control Filter 可以把若干个节点组合在一起,赋予对应的权限,这样可以达到用一个权限控制多个节点的效果。
看不懂 ['jdfenlei_id'=>'id'] 部分,这里应该是一个字符串或者 attribute list 才对。
你能把 composer.json 贴出来吗?尤其是
minimum-stability
和require
属性的值。一般我在name字段都是存储的节点的形式,如:modules/controll/action
Yii2 RBAC 表格内不是用来存储路由(route, 即你说的“节点”)的。路由的权限判断通过 ACF (Access Control Filter) 实现。
在做项目的时候不可能就用他原原本本的就能满足客户的一些需求,可以在他的源结构中扩展加一些字段……
你说的有道理,前提是你对 Yii2 RBAC 相关知识通读过,有一个整体的、大致的认识。当自己的需求不能实现时,大致有两种可能:一、某个知识点能解决需求,但是该知识点自己不知道;二、需求比较特殊,框架中提供的通用功能满足不了特殊的需求。解决办法是新建一个子类,在子类中进行个性化定制。
如:我有50个权限要检查 YIi会这样去查:
SELECT * FROM data00200 ***
你确定 Yii2 是这样查找的吗?还是 ThinkPHP 是这么查的,所以你觉得 Yii2 也是这么做的?我对 RBAC 了解有限,没有找到这里的出处。
我觉得你走进了一个误区:有意无意地,带着 ThinkPHP 已有的知识结构去理解 Yii2. 框架间的实现原理的确类似,数据结构也可能差别不大,但是实现思路上可能存在差别。
试试
$columnName = 'column1'; $record->{$columnName} = 'xxx';