Laravel Nova中多态关联失效,请求问题排查帮助
customFieldValueable_type列 我配置了以下Laravel模型及关联关系:
App\Subscriber.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Grosv\LaravelPasswordlessLogin\Traits\PasswordlessLogin; class Subscriber extends Authenticatable { use Notifiable, PasswordlessLogin; public function customFieldValues() { return $this->morphMany(CustomFieldValue::class, 'customFieldValueable'); } }
App\CustomField.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Models\Campaign; class CustomField extends Model { protected $fillable = [ 'name', 'key', 'type', 'field_options' ]; public function customFieldValues() { return $this->hasMany(CustomFieldValue::class); } }
App\CustomFieldValue.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class CustomFieldValue extends Model { use HasFactory; protected $fillable = ['custom_field_id', 'value', 'custom_field_valueable_id', 'custom_field_valueable_type']; public function customField() { return $this->belongsTo(CustomField::class); } public function customFieldValueable() { // If you are using custom column names, specify them here. Otherwise, ensure they match the migration. return $this->morphTo(null, 'custom_field_valueable_type', 'custom_field_valueable_id'); } }
App\Campaign.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Models\CustomField; class Campaign extends Model { protected $dates = [ 'imported_at' ]; protected $casts = [ 'imported_at' => 'datetime', 'exported_at' => 'datetime' ]; protected $fillable = [ 'uuid', 'name', 'slug', 'client_id' ]; public function customFieldValues() { return $this->morphMany(CustomFieldValue::class, 'customFieldValueable'); } }
App\Newsletter.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Newsletter extends Model { protected $fillable = [ 'uuid', 'name', 'brand_id', 'active', 'create_send_list_id', 'last_imported' ]; public function brand() { return $this->belongsTo(Brand::class); } public function subscribers() { return $this ->belongsToMany(Subscriber::class) ->withPivot('active') ->withTimestamps(); } public function customFieldValues() { return $this->morphMany(CustomFieldValue::class, 'customFieldValueable'); } }
对应的迁移文件如下:
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('custom_field_values', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('custom_field_id'); $table->string('value'); // Manually create the polymorphic columns $table->unsignedBigInteger('custom_field_valueable_id'); $table->string('custom_field_valueable_type'); // Manually specify a shorter index name $table->index(['custom_field_valueable_type', 'custom_field_valueable_id'], 'custom_field_valueable_index'); $table->timestamps(); $table->foreign('custom_field_id')->references('id')->on('custom_fields')->onDelete('cascade'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('custom_field_values'); } };
在Laravel Nova界面查看Subscriber时,出现如下错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'custom_field_values.customFieldValueable_type' in 'where clause' (Connection: mysql, SQL: select * from
custom_field_valueswherecustom_field_values.customFieldValueable_type= App\Models\Subscriber andcustom_field_values.customFieldValueable_id= 1016 andcustom_field_values.customFieldValueable_idis not null order bycustom_field_values.iddesc limit 6 offset 0)
我是多态关联的新手,希望有人能帮我找出问题所在。
问题核心是多态关联名称与数据库列名的命名规则不匹配:
- 数据库迁移中,多态列采用蛇形命名:
custom_field_valueable_type、custom_field_valueable_id - 但你在
morphMany关联中使用的是驼峰命名的customFieldValueable作为关联标识,Laravel自动转换列名时出现偏差,导致SQL查询错误地使用了驼峰格式的列名。
有两种修复方式:
方式一:统一关联名称为蛇形(推荐)
修改所有模型中的customFieldValues关联方法,将关联标识改为蛇形的custom_field_valueable,符合Laravel命名规范:
// Subscriber.php、Campaign.php、Newsletter.php中统一修改 public function customFieldValues() { return $this->morphMany(CustomFieldValue::class, 'custom_field_valueable'); }
这样Laravel会自动匹配到数据库中对应的蛇形列名,无需额外配置。
方式二:在morphMany中手动指定列名
如果不想修改关联名称,可在每个morphMany方法里明确指定多态列的名称:
// Subscriber.php、Campaign.php、Newsletter.php中统一修改 public function customFieldValues() { return $this->morphMany( CustomFieldValue::class, 'customFieldValueable', 'custom_field_valueable_type', 'custom_field_valueable_id' ); }
手动绑定关联标识与数据库列的对应关系,强制框架使用正确的列名查询。
内容的提问来源于stack exchange,提问作者Udders

