Yii2用户授权报错:Call to a member function get() on null求助
排查"Call to a member function get() on null"报错的原因及解决方案
这个报错的核心是你在调用$user->balance->get(...)时,$user->balance返回了null——也就是说当前用户对应的UserBalance记录不存在,或者关联关系没正确建立。结合你的代码,主要问题出在以下几个关键点:
1. 重写的signup方法未执行父类核心逻辑,导致User记录未创建或关联ID错误
看你的RegistrationForm.php里的signup方法:
public function signup() { \Yii::$app->db->transaction(function() { (new UserBalance([ 'user_id' => $this->id, 'silver_in' => 100 ]))->save(); $value = SettingHelper::get('user.count') + rand(1, 10); SettingHelper::set('user.count', $value); }); }
你完全覆盖了父类的signup方法,但没有调用parent::signup()——而dektrium/yii2-user的父类方法才是负责创建User记录、生成用户ID的核心流程。
这会引发两个致命问题:
$this->id此时根本没有值(因为User记录还没被创建),导致你创建的UserBalance的user_id为null,后续用户登录后,$user->balance找不到对应记录,自然返回null。- 父类的注册逻辑没执行,用户的基础记录都没创建成功,整个注册流程不完整。
修复方案:
先调用父类方法完成User记录的创建,再用返回的User实例ID去创建UserBalance:
public function signup() { // 先执行父类逻辑,创建User记录并返回实例 $user = parent::signup(); if ($user === null) { return null; // 父类创建失败时直接返回,终止流程 } \Yii::$app->db->transaction(function() use ($user) { $balance = new UserBalance([ 'user_id' => $user->id, // 使用已创建的User实例的有效ID 'silver_in' => 100 ]); // 可以根据需求选择是否跳过验证,或者添加错误处理 if (!$balance->save()) { throw new \Exception('创建用户余额失败: ' . implode(', ', $balance->getErrorSummary(true))); } $value = SettingHelper::get('user.count') + rand(1, 10); SettingHelper::set('user.count', $value); }); return $user; // 记得返回User实例,符合父类方法的返回规范 }
2. 关联加载的额外验证点
修复signup逻辑后,建议做以下验证确保关联正常:
- 直接查看
user_balance表,确认注册后的用户对应的user_id字段是否正确赋值。 - 在需要调用
balance->get()的地方,可主动加载关联,比如用$user->getBalance()->one()替代直接$user->balance,避免延迟加载的潜在问题。
3. 事务内的错误处理补充
你的事务中调用save()时没有处理失败场景,如果UserBalance因验证规则或数据库问题保存失败,事务会回滚但没有任何提示。添加错误抛出或日志记录,能帮助你快速定位后续问题。
总结
最核心的问题是重写signup方法时遗漏了父类的核心逻辑,导致User记录未正确创建,进而让UserBalance的关联关系完全无效。修复这个问题后,用户登录时$user->balance就能正确获取到对应记录,也就不会出现调用get()方法时的null报错了。
内容的提问来源于stack exchange,提问作者GaLana
相关产品推荐
相关产品推荐

