Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not execute has/whereHas on MorphTo relation. #25724

Closed
dkulyk opened this issue Sep 21, 2018 · 8 comments
Closed

Can not execute has/whereHas on MorphTo relation. #25724

dkulyk opened this issue Sep 21, 2018 · 8 comments

Comments

@dkulyk
Copy link
Contributor

dkulyk commented Sep 21, 2018

  • Laravel Version: 5.7.5
  • PHP Version: 7.2.10
  • Database Driver & Version: MySQL 10.2.17-MariaDB

Description:

Can not execute has/whereHas on MorphTo relation.
It throws RuntimeException('has() and whereHas() do not support MorphTo relationships.')
It happened after #25337

Steps To Reproduce:

Search all entities where exists $relatedEntity.

//Manually set entity type.
$builder->where('entity_type', $relatedEntity->getMorphClass());
$builder->getModel()->setAttribute('entity_type', $relatedEntity->getMorphClass());

$builder->whereHas('entity', function(Builder $builder) {
   //...
});
@staudenmeir
Copy link
Contributor

As #25337 says, has() and whereHas() don't support MorphTo relationships.

#5429 and #18523 provide a detailed explanation and possible workarounds.

@laurencei
Copy link
Contributor

Thanks @staudenmeir

@dkulyk
Copy link
Contributor Author

dkulyk commented Sep 21, 2018

They are support MotphTo relationships. But need specify a type, then it known what a table need to use.

if someone does not understand how MotphTo works, then the rest do not need to be deprived of the opportunity to use it.

@staudenmeir
Copy link
Contributor

Revert to Laravel <5.6.35 and replace ->get() on your $builder query with ->toSql(). What's the result?

@dkulyk
Copy link
Contributor Author

dkulyk commented Sep 21, 2018

It worked in L5.5, after upgrading to 5.7 it doesn't work
L5.5:

>>> $q = \DtKt\Comments\Entities\Comment::query()
>>> $q->getModel()->entity_type = 'seminar_page';
>>> $q->where('entity_type','seminar_page')->whereHas('entity')
>>> $q->toSql()
=> "select * from `comments` where `entity_type` = ? and exists (select * from `seminars_pages` where `comments`.`entity_id` = `seminars_pages`.`id`) and `comments`.`deleted_at` is null"
>>> $q->getBindings()
=> [
     "seminar_page",
   ]

With different model for example L5.7 with disabled exception.

>>> $q = \DtKt\Comments\Entities\Comment::query()
>>> $q->getModel()->entity_type = \DtKt\Comments\Entities\Comment::class;
>>> $q->where('entity_type','seminar_page')->whereHas('entity')
>>> $q->toSql()
=> "select * from `comments` where `entity_type` = ? and exists (select * from `comments` as `laravel_reserved_0` where `laravel_reserved_0`.`id` = `comments`.`entity_id`) and `comments`.`deleted_at` is null"
>>> $q->getBindings()
=> [
     "seminar_page",
   ]

Example of production code: Search comments for entities.
$has is Closure like as Builder::has from L5.7 without exception.

foreach (Comments::all() as $name) {
    $builder->orWhere(function (Builder $builder) use ($has, $name, $search) {
        /* @var Model $entity */
        $entity = Comments::resolve($name);
        $builder->where('entity_type', $entity->getMorphClass());
        $builder->getModel()->setAttribute('entity_type', $entity->getMorphClass());
        $has->call($builder, 'entity', '>=', 1, 'and',
            function (Builder $builder) use ($search) {
                Nova::resourceForModel($builder->getModel())::applySearch($builder, $search);
            }
        ]);
    });
}

@staudenmeir
Copy link
Contributor

How is the entity relationship defined?

@dkulyk
Copy link
Contributor Author

dkulyk commented Sep 21, 2018

HasMorphEntity.php

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

@staudenmeir
Copy link
Contributor

Laravel 5.8.27 will add whereHasMorph(): #28928

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants