Search code examples
phplaraveleloquenteloquent-relationship

Laravel Eloquent Query Error: Undefined Column in Polymorphic Relationship


the following code throws an error with WhereHasMorph and returns all data without the condition being applied, when WhereHas is used on the polymorphic relationship. Does anyone know where the problem is?

            $personQuery = Person::query();
            $column = 'value';
            $needle = '%09133333%';
            $personQuery->orWhereHasMorph('digitalContacts', '*', function ($contactQuery) use ($column, $needle) {
                $contactQuery->where($column, 'like', '%' . $needle . '%');
            });

            $data =  $personQuery->get();

the error:

{
    "success": false,
    "payload": [],
    "errors": [
        {
            "type": "warning",
            "code": "42703",
            "message": "SQLSTATE[42703]: Undefined column: 7 ERROR:  column \"digital_contactable_type\" does not exist\nLINE 1: select distinct \"digital_contactable_type\" from \"people\"\n                        ^ (Connection: tenant, SQL: select distinct \"digital_contactable_type\" from \"people\")"
        }
    ]
}

The error message I received indicates that the column "digital_contactable_type" does not exist in the "people" table. but it should look for the digital_contactable_type on the digital_contacts table, not the people!

relations are defined on the models like these:

class Person extends Model
{
    public function digitalContacts()
    {
        return $this->morphMany(DigitalContact::class, 'digital_contactable', 'digital_contactable_type');
    }
    //...

}
class DigitalContact extends Model
{
    public function digitalContactable()
    {
        return $this->morphTo();
    }
        //...

}

and the related columns on the tables are defined like the following:

        Schema::create('people', function (Blueprint $table) {

            $table->unsignedBigInteger('id', true);
            //...
            $table->timestamps();
        });
        Schema::create('digital_contacts', function (Blueprint $table) {
            $table->unsignedBigInteger('id', true);
            $table->unsignedBigInteger('digital_contactable_id');
            $table->string('digital_contactable_type'); // person, organization, etز
            $table->string('value');
            //...
            $table->timestamps();
        });

any Ideas?


Solution

  • first of all, the relationship name on the morphMany should match the relationship name on the morphTo. so in my case, the digitalContacts relation defined on the person model should look like this:

    public function digitalContacts()
    {
        return $this->morphMany(DigitalContact::class, 'digitalContactable', 'digital_contactable_type', 'digital_contactable_id');
    }
    

    and also apparently, there is no orWhereHasMorph. you can simply use orWhereHas.