skip to Main Content

I have the following Models and relationships.

AppSubscriber.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;
use IlluminateSupportFacadesDB;
use IlluminateSupportStr;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use GrosvLaravelPasswordlessLoginTraitsPasswordlessLogin;

class Subscriber extends Authenticatable
{
    use Notifiable, PasswordlessLogin;

    public function customFieldValues()
    {
        return $this->morphMany(CustomFieldValue::class, 'customFieldValueable');
    }
}

AppCustomField.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;
use AppModelsCampaign;

class CustomField extends Model
{
    protected $fillable = [
        'name',
        'key',
        'type',
        'field_options'
    ];

    public function customFieldValues()
    {
        return $this->hasMany(CustomFieldValue::class);
    }
}

AppCustomFieldValues.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

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');
    }
}

AppCampaign.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;
use AppModelsCustomField;

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');
    }
   }

AppNewsletter.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

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');
    }
}

My migration to create the table to support this looks like this,

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

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');
    }
};

However in the Nova interface when I try and view a subscriber I get the following error,

SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘custom_field_values.customFieldValueable_type’ in ‘where clause’ (Connection: mysql, SQL: select * from custom_field_values where custom_field_values.customFieldValueable_type = AppModelsSubscriber and custom_field_values.customFieldValueable_id = 1016 and custom_field_values.customFieldValueable_id is not null order by custom_field_values.id desc limit 6 offset 0)

If someone could explain to me where I have gone wrong that would great. I am very new to polymorphic relationships.

2

Answers


  1. the laravel query is looking for a column customFieldValueable_type but you have a custom_field_valueable_type in your db.

    The error seems to be coming from the AppCustomFieldValues.php specifically in the function:

    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');
    }
    

    The correct naming conventions can be found here in the laravel docs.

    The conventions should be:

    public function customFieldValueable(): MorphTo
    {
        return $this->morphTo(__FUNCTION__, 'custom_field_valueable_type', 'custom_field_valueable_id');
    }
    

    If you want to use the standard naming convention:

    public function customFieldValueable(): MorphTo
    {
        return $this->morphTo();
    }
    

    And then change the db columns name accordingly

    Login or Signup to reply.
  2. try like this:

    return $this->morphTo('custom_field_valueable');
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search