-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
issue with query select override #21472
Comments
A quick observation from someone that hasn't understood the problem; if there's a code commit that attempted to fix your problem, but didn't, then you totally failed to provide clear steps to reproduce the problem, and as such the coder couldn't reproduce your exact problem or verify the fix properly. Hint hint. Can you provide a test that currently fails, but should work? |
Hi @sisve the fix in #21468 fix a specific case where explained in #21116 and #21464 , but not the entire problem, the explanation is based on that test cases of that PR #21468 , so I agree it's not very friendly, thanks for your suggestion Here is the simplest way to reproduce the problem, run this in tinker
it will output correct SQL for first query.
and it will output wrong SQL (Bindings) once columns have been override
so mysql will run query as |
Hey Here's another way to reproduce $stories = Story::published()
->whereHas('organisation.company', function ($query) use ($company) {
$query->whereNotNull('published_at');
$query->where('companies.id', '=', $company->id);
})
->get()
; When calling select * from `stories` where `published_at` is not null and exists (select * from `organisations` where `stories`.`organisation_id` = `organisations`.`id` and exists (select * from `companies` where `organisations`.`id` = `companies`.`organisation_id` and `published_at` is not null and `companies`.`id` = ?)) and `stories`.`deleted_at` is null When calling array:5 [
0 => "companies"
1 => "companies"
2 => "companies"
3 => "companies"
4 => 549
] @themsaid The PR #21486 fixed the issue, so no idea why it was declined saying it's not a bug when it's clearly a way to use Eloquent and it's clearly a bug on the framework. Edit: Just to keep it in perspective, this only happens if we use the |
Hi @brunogaspar, I do agree this is clearly a bug, but @themsaid have a good point that this might break someone's code as it's not fully back-ward compatible. |
I'm on 5.5.14 which was tagged yesterday and it doesn't work. I tried before coming here and "complain" 😁 With your changes, it does work. |
@brunogaspar can you share your three model class? more specifically which model have withCount on which model and anything else related in these models so I can reproduce your error and find out a patch for that? |
Of course.. Organisation.php <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Organisation extends Model
{
protected $table = 'organisations';
public function company()
{
return $this->hasOne(Company::class, 'organisation_id');
}
public function stories()
{
return $this->hasMany(Story::class, 'organisation_id');
}
} Company.php <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Company extends Model
{
protected $table = 'companies';
protected $dates = ['published_at'];
protected $withCount = [
'categories',
'countries',
'contacts',
'followers',
];
public function categories()
{
return $this
->morphToMany(Category::class, 'entity', 'categories_morphed')
->withTimestamps()
;
}
public function countries()
{
return $this
->morphToMany(Country::class, 'entity', 'countries_morphed')
->withTimestamps()
;
}
public function contacts()
{
return $this
->morphToMany(User::class, 'entity', 'contacts_morphed')
->withTimestamps()
;
}
public function followers()
{
return $this->morphMany(Follower::class, 'followable');
}
public function organisation()
{
return $this->belongsTo(Organisation::class, 'organisation_id');
}
} Story.php <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Story extends Model
{
useSoftDeletes;
protected $dates = [
'published_at',
'deleted_at',
];
public function organisation()
{
return $this->belongsTo(Organisation::class, 'organisation_id');
}
}
|
@brunogaspar if you add More places are
So it's better wait @themsaid 's suggestion here, for your reference i created a test file that will fail, and work if add |
Thanks @shwhl i'll have a look in a bit and will let you know. Again, thanks. Really appreciated! |
@shwhl Having that change on |
that's good! |
I'd mark this as a no-fix, there's no safe way I can think of where this can be fixed without breaking people apps. It's a rare edge case in my opinion. |
@themsaid Sorry to come back to this, but i don't really agree when you say "it's a rare edge case". Basically, this is a feature that doesn't work as expected, and i have to assume here, because it was not implemented properly, which is fine, was implemented through a PR i believe. However, when using But anyway.. if the ✌️ |
I'm having the same problem as well. Basically this is my query - it gets the number of members within a specified distance. Member::query()
->addSelect(\DB::raw("ROUND((3959 * acos( cos(radians($latitude)) * cos(radians( `members_data_members`.`data_latitude` )) * cos( radians( `members_data_members`.`data_longitude` ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians(`members_data_members`.`data_latitude`) ) ) ), 0) AS distance"))
->having('distance', '<=', $miles)
->count(); This fails as the select is overriden. Maybe this is an "edge case" but I don't believe so, either. Any folks who use use a dynamic expression and |
I'm re-opening issue #21464 , I believe fix #21468 didn't fix the problem.
@themsaid the reason why I put clear binding into select method is because no matter where select method is called, the clean method won't affect the code, your fix only fix the problem with
withCount
, but user can still face same issue, if like your test case,Third
have global scopewhere status = 1
and using this query on second.Second
haveprotected $withCount = ['thirds'];
we just need call this
in this code, it will override select like how it does in
withCount
, if runit will show
the final SQL will be wrong too, it will be
select "id" from "seconds" where "foo" = 1
my conclusion is whatever case, as long as
select()
method being called, it's overriding original select columns, this method is not likeaddSelect()
, all old bindings forselect
should be all cleared, so we should put a global binding clean code there.For the simplest way to reproduce bug, check comment below.
Created PR #21486
The text was updated successfully, but these errors were encountered: