使用Laravel Eloquent将文章与视频存入关联模型的问题
Laravel 多态关联attach返回null问题解决
问题场景
创建了名为savables的迁移表,用于实现Post/Video模型与User模型的多态关联(关联/解除关联post_id/video_id及其模型类型),迁移代码如下:
Schema::create('savables', function (Blueprint $table) { $table->unsignedBigInteger('savable_id'); $table->string('savable_type'); });
User、Post和Video模型定义了以下关联方法:
/* Post和Video模型 */ public function users_saved(): MorphToMany { return $this->morphToMany(User::class, 'savable'); } /* User模型 */ public function saved_posts(): MorphToMany { return $this->morphedByMany(Post::class, 'savable'); } public function saved_videos(): MorphToMany { return $this->morphedByMany(Video::class, 'savable'); }
执行语句$post->saved_posts()->attach(auth()->id());返回null,需解决该问题。
解决方法
1. 修正关联方法调用错误
saved_posts()是User模型中定义的关联方法,用于获取用户收藏的帖子;而Post模型对应的关联方法是users_saved(),用于获取收藏该帖子的用户。
正确的调用语句应为:
$post->users_saved()->attach(auth()->id());
2. 完善迁移表结构
Laravel多态关联的中间表需要包含关联双方的外键,当前迁移表仅定义了savable_id和savable_type,缺少关联User模型的user_id字段,同时建议添加复合主键避免重复关联记录。修改后的迁移代码:
Schema::create('savables', function (Blueprint $table) { $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('savable_id'); $table->string('savable_type'); // 设置复合主键,防止同一用户重复收藏同一内容 $table->primary(['user_id', 'savable_id', 'savable_type']); // 添加外键约束(可选,用于保证数据完整性) $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); });
3. 显式指定中间表名(可选)
如果迁移表名称不符合Laravel默认命名规则(默认按关联模型名字母顺序拼接),需在关联方法中显式指定表名,同时可按需添加时间戳字段:
// Post/Video模型中 public function users_saved(): MorphToMany { return $this->morphToMany(User::class, 'savable') ->table('savables') ->withTimestamps(); } // User模型中 public function saved_posts(): MorphToMany { return $this->morphedByMany(Post::class, 'savable') ->table('savables') ->withTimestamps(); }
(若添加withTimestamps(),需在迁移表中补充$table->timestamps();字段)
内容的提问来源于stack exchange,提问作者Sadan Khan
相关产品推荐
相关产品推荐

