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

[5.5] whereHas bindings are duplicated when using $withCount #21116

Closed
TheAlexLichter opened this issue Sep 10, 2017 · 8 comments
Closed

[5.5] whereHas bindings are duplicated when using $withCount #21116

TheAlexLichter opened this issue Sep 10, 2017 · 8 comments

Comments

@TheAlexLichter
Copy link
Contributor

TheAlexLichter commented Sep 10, 2017

  • Laravel Version: 5.5.3
  • PHP Version: 7.0.22-0ubuntu0.17.04.1
  • Database Driver & Version: PDO (mysqlnd 5.0.12-dev, SQLite: 3.16.2)

Description:

The QueryBuilder bindings are duplicated when using whereHas() while using $withCount on the related Model. This leads to problems when using MorphToMany relations, because queries like this are created through Eloquent:

image

Obviously, the tipable_id is "set wrong" here because the first parameter was duplicated.

Steps To Reproduce:

  1. Setup a fresh Laravel 5.5.3 copy

  2. Issue the commands php artisan make:model Comment -m php artisan make:model Post -m and php artisan make:model Video -m

  3. Add the following code to the Comment model:

 public function posts()
    {
        return $this->morphedByMany(Post::class, "commentable");
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, "commentable");
    }
  1. Add this code to the Post model:
 protected $withCount = ["comments"];

    public function comments()
    {
        return $this->morphToMany(Comment::class, "commentable");
    }
  1. Now add another piece of code to the Video model:
public function comments()
    {
        return $this->morphToMany(Comment::class, "commentable");
    }
  1. Finally add a migration for the commentables table through php artisan make:migration create_commentables_table and add those scheme definitions:
$table->integer('comment_id');
$table->morphs('commentable');
  1. Create a new test by using php artisan make:test HereIsTheBugTest

  2. Use the following snippet as the test:

 use RefreshDatabase;

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testThatItFails()
    {
        $p = Post::create();
        $v = Video::create();
        $c = new Comment();

        $c->save();
        $c->posts()->save($p);
        $c->videos()->save($v);

        $this->assertTrue(Comment::first()->is($c));

        $testPost = Post::firstOrFail();
        $this->assertTrue($testPost->is($p));

        $builder = Comment::whereHas("posts");

        $this->assertTrue($c->is($builder->firstOrFail()));
    }
  1. Setup your phpunit.xml to use a testing in-memory database by adding:
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
  1. Don't forget to fix your database.php file (see here)

  2. Run the test and see it fail!

1) Tests\Feature\HereIsTheBugTest::testThatItFails
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 25 bind or column index out of range (SQL: select * from "comments" where exists (select * from "posts" inner join "commentables" on "posts"."id" = "commentables"."commentable_id" where "comments"."id" = "commentables"."comment_id" and "commentables"."commentable_type" = App\Post) limit 1)

Related issues

#20640

@TheAlexLichter TheAlexLichter changed the title Eloquent bug: WhereHas bindings are duplicated when using $withCount [5.5] whereHas bindings are duplicated when using $withCount Sep 11, 2017
@Dylan-DPC-zz
Copy link

The problem isn't with withCount but with whereHas. This is a known problem (ref #5429 #13585 #18523)

@TheAlexLichter
Copy link
Contributor Author

@Dylan-DPC whereHas is only a problem in combination with polymorphic relations when the relations aren't strictly defined, which isn't the case here. As you can see in the example app, whereHas works well when you have two relation functions (posts for all entries that have the type App\Models\Post and videos for all video entries).

If you remove the $withCountvariable of the Post Model inside the test application you can see that the test I've created passes.

@themsaid
Copy link
Member

Please include code in your steps of replication, including an entire laravel application in a .zip file won't help :)

What code should I run in a fresh laravel project to be able to replicate?

@TheAlexLichter
Copy link
Contributor Author

@themsaid I've updated the information concerning that issue and added the whole code for reproduction!

@Dylan-DPC-zz
Copy link

It is better to push the repo on GH and share the link. That way people can clone it and try it directly. Works better than the zip 👍

@TheAlexLichter
Copy link
Contributor Author

You are right @Dylan-DPC 🙈 Why didn't I think of that before? 😅

@brunogaspar
Copy link
Contributor

Unfortunately i have this issue as well.

Seems like this $withCount property feature was not implemented properly :\

@TheAlexLichter
Copy link
Contributor Author

Looks like this issue is a duplicate of #21464
Fortunately, there is a fix incoming #21468

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

No branches or pull requests

4 participants