Laravel使用morpToMany关联Movie与Cast时出现字段不存在错误
Laravel多态关联报错:SQLSTATE[42S22] 找不到
movie_casts.movie_casts_id列 问题重现
尝试用morphToMany关联Movie和Cast模型时触发错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'movie_casts.movie_casts_id' in 'field list'
相关代码如下:
Movie模型
public function casts() { return $this->morphToMany(Cast::class, 'movie_casts'); }
Cast模型
public function movies() { return $this->morphToMany(Movie::class, 'movie_casts'); }
MovieCast模型
public function movies() { return $this->morphedByMany(Movie::class, 'movie_casts'); } public function casts() { return $this->morphedByMany(Cast::class, 'movie_casts'); }
movie_casts表结构
$table->unsignedBigInteger('cast_id')->nullable(); $table->foreign('cast_id')->references('id')->on('casts'); $table->unsignedBigInteger('movie_id')->nullable(); $table->foreign('movie_id')->references('id')->on('movies');
控制器代码
public function moviesList() { $movies = Movie::all(); foreach($movies as $movie){ $moviesWithCast = $movie->casts; }; return response()->json( $moviesWithCast, 200 ); }
错误原因
你混淆了普通多对多关联和多态多对多关联的核心规则:
- 多态多对多关联要求中间表必须包含
{关联名称}_id和{关联名称}_type两个字段,但你的表用的是movie_id和cast_id,完全不符合多态关联的结构要求。 morphToMany的第二个参数是多态关联的标识名称(比如castable),而你传入的movie_casts是中间表名,导致框架错误地去查找movie_casts_id字段。
解决方案
情况1:使用普通多对多关联(适配当前表结构)
如果Movie和Cast只是单纯的多对多关系(不需要关联其他模型到该中间表),直接改用belongsToMany即可:
- 修改Movie模型:
public function casts() { return $this->belongsToMany(Cast::class, 'movie_casts'); }
- 修改Cast模型:
public function movies() { return $this->belongsToMany(Movie::class, 'movie_casts'); }
- 删除
MovieCast模型(普通多对多无需中间表模型,除非需要处理额外字段逻辑)
情况2:改用标准多态多对多关联(需扩展关联能力)
如果需要让其他模型(比如TvShow)也关联Cast,需调整表结构和模型:
- 修改中间表结构(新建或迁移):
$table->unsignedBigInteger('cast_id'); $table->foreign('cast_id')->references('id')->on('casts'); // 多态核心字段 $table->unsignedBigInteger('castable_id'); $table->string('castable_type'); // 复合主键 $table->primary(['cast_id', 'castable_id', 'castable_type']);
- 修改Movie模型:
public function casts() { return $this->morphToMany(Cast::class, 'castable', 'castables'); }
- 修改Cast模型:
public function movies() { return $this->morphedByMany(Movie::class, 'castable', 'castables'); }
- 中间表模型(
Castable):
public function castable() { return $this->morphTo(); } public function cast() { return $this->belongsTo(Cast::class); }
控制器代码优化
原控制器代码中循环会覆盖moviesWithCast变量,最后仅返回最后一条数据,建议改用预加载避免N+1查询:
public function moviesList() { $movies = Movie::with('casts')->get(); return response()->json($movies, 200); }
内容的提问来源于stack exchange,提问作者user20597340
相关产品推荐
相关产品推荐

