Laravel执行php artisan migrate报非对象id属性读取错误如何解决
错误原因
- 执行
php artisan migrate时,当前迁移文件对应代码执行到$plan = Plan::find(1)这行时,plans表中不存在ID为1的记录,find方法查询不到对应数据会返回null,后续尝试访问null的id属性就触发了「Trying to get property 'id' of non-object」报错。 - 根本诱因通常有两个:一是插入套餐默认数据的迁移执行时间晚于当前管理员数据填充的迁移,跑当前迁移时套餐数据还没写入;二是代码硬编码依赖固定ID的记录,本身兼容性差,只要对应ID的数据不存在就会崩溃。
修复方案
方案1:调整迁移执行顺序
找到写入默认套餐数据的迁移文件,将其文件名前缀的时间戳修改为早于2021_06_04_055759的数值,保证迁移执行时先写入套餐数据,再执行当前管理员数据填充逻辑。方案2:在当前迁移中补充套餐创建逻辑(更稳妥)
不依赖已存在的套餐数据,直接在当前迁移内先创建所需套餐再关联,同时可顺便修正硬编码user_id=1的潜在问题,修改后的up方法代码如下:
public function up() { // seed admin user $admin = User::create([ 'name' => 'Admin', 'email' => 'admin@admin.se', 'password' => Hash::make('password'), 'plan_id' => null, ]); $admin->assignRole(['administrator', 'company']); // 不存在ID为1的套餐则创建,存在则直接返回对应实例 $plan = Plan::firstOrCreate( ['id' => 1], [ // 按业务实际需求补全套餐必填字段 'name' => '默认套餐', 'interval' => 'monthly', 'price' => 0 ] ); Subscription::create([ 'user_id' => $admin->id, // 直接使用刚创建的管理员ID,避免自增ID不连续导致的错误 'plan_id' => $plan->id, 'starts_at' => Carbon::now(), 'ends_at' => $plan->interval == 'monthly' ? Carbon::now()->addMonth() : Carbon::now()->addMonths(12), ]); }
方案3:逻辑拆分到数据填充器(符合Laravel规范)
迁移仅负责表结构变更,将这类业务基础数据填充的逻辑移动到database/seeders目录下的Seeder文件中,迁移执行完成后单独运行php artisan db:seed命令完成数据填充,逻辑拆分更合理。
内容的提问来源于stack exchange,提问作者Istiak Mahmood
相关产品推荐
相关产品推荐

