Conversation
A field handle that collides with one of ElementQuery's own properties (e.g. `where`) was still being added to criteriaAttributes(), so getCriteria() returned internal query state rather than a field value. That leaked one element's relation constraint into the shared EagerLoadPlan built by ElementQuery::eagerLoad(), which made relational fields nested within Matrix fields fail count validation for every sibling element except the first.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bit by an old legacy site that was created before
wheremade it in to the blacklisted field names. Have a fix for it here, if you'd like… not sure if it's something you want to account for though.On an install with a custom field whose handle collides with an
ElementQueryproperty (ours iswhere), relational fields nested in Matrix fields fail validation with "should contain at least 1 selection" on rows that have a selection.whereis inRESERVED_HANDLES, but that's only validated on save, so fields created before the handle was reserved are still out there. Ours is a Redactor field on an unrelated entry type.Repro
Custom field handled
where. Matrix field whose entry type has an Entries subfield withminRelationsof 1. Two or more Matrix entries, each related to a different entry. Save the owner.Every row but the first fails. Point them all at the same entry and it passes.
Debugging
criteriaAttributes()adds behavior properties without checking whether the handle collides with a property the query already has. On collision the query property wins on read, sogetCriteria()returns the SQL condition:validateRelationCount()calls_all()->eagerly(), andcount()routes intoeagerLoad(), which passes$this->getCriteria()into the plan. Row 225's target restriction then constrains the shared target query for every sibling.eagerLoadElements()seeds each source to 0 and only overwrites non-zero counts, so the rest keep the 0, andcount()returns it rather than falling back to a real query.validateRelatedElements()has the same exposure (->eagerly()then->all()): siblings come back empty and skip validation. Not fixed here.Fix
Only the validation path is affected.
eagerlyis off by default, and->all(),->one(), and explicitwith()eager loading were all already correct. Colliding handles also drop out ofgetCriteria(), but they were never usable as params anyway.Two tests in
ElementQueryTest, both failing without the fix. Full unit suite passes.Separately:
select,from,join,having,params,orderBy,limit,offset,groupBy,union,distinct, andindexByare all public query properties and none are inRESERVED_HANDLES.