Repository navigation
Filter by a relation path in Filter::related(), and fix criteria path errors - #9
Merged
Merged
Conversation
`Filter::related()` takes a dotted relation path, such as
`tags.category`, and nests one related filter per relation:
`related('tags.category', $criteria, $visibility)` is
`related('tags', related('category', $criteria, $visibility))`. As in
a `Load` path, the criteria and visibility belong to the last relation,
and the relations before it see their active rows; nested calls still
give them conditions or a visibility of their own. The path is expanded
when the filter is built, so the compiler and the comparison of load
settings see the same value as the hand-written nesting.
Unlike a path in a criteria key, which stays BelongsTo-only, the path
goes through to-many relations: all conditions of the call match one
row of the last target. Empty segments and SQL fragments are rejected
as before.
Tests cover paths through BelongsTo, BelongsToMany and three relations,
equal to the nested calls in value and SQL, the visibility of the last
relation, and a path in the nested-locale test on the real databases.
A criteria path whose first segment is a number, such as `1.code`, threw a TypeError: PHP keeps the segment as an integer key of the array that groups the conditions of one target. It is an unknown relation, as any other name no relation has, and is rejected with InvalidArgumentException. A write whose criteria name a path through an unknown relation said the relation is unknown, where a path through a known one said that paths are for reads. The check for a read now comes before the relation is looked up, so both say the latter. findOrFail() is described by what it does: it answers as not found an ID that the type of the key rejects, such as "007" for an integer key, not every ID no row can have. What the column holds is known to the server only, so an ID that only the server rejects stays its error: on PostgreSQL, a number beyond the column's range, or a string that is not a UUID for a uuid column. The API reference names the version it describes, 1.5, where it still said 1.2. Tests cover paths that start and end with a number, and writes with a path or a related filter on an unknown relation.
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.
Prepares
v1.5.0:Filter::related()takes a relation path, two errors of criteria paths from 1.4.0 are fixed, and the documentation says whatfindOrFail()answers as not found.Changes
Filter::related()takes a dotted relation path, such astags.category, through relations of any kind, and nests one related filter per relation:related('tags.category', $criteria, $visibility)isrelated('tags', related('category', $criteria, $visibility)). As in aLoadpath, the criteria and visibility belong to the last relation, and the relations before it see their active rows; nested calls still give them conditions or a visibility of their own. The path is expanded when the filter is built, so the compiler is unchanged and sees the hand-written nesting. A path in a criteria key staysBelongsTo-only.['1.code' => ...], threw aTypeError: PHP keeps the segment as an integer key of the array that groups the conditions of one target. It is now rejected withInvalidArgumentException, as any other unknown relation.PredicateCompiler::assertReadQuery()), so both say the latter.findOrFail()answers as not found. It is an ID no visible row has, or one the type of the key rejects, such as"007"for an integer key; the docs said "an ID no row can have", which the package cannot know. An ID that only the server rejects stays the driver's exception. On PostgreSQL 17 these were checked on the server: a number beyond the range of anINTEGER,SMALLINTorBIGINTcolumn (22003), a string that is not a UUID for auuidcolumn (22P02) and broken UTF-8 (22021); MySQL 8.4 answers all of them as not found. The mapped type does not tell what the column holds (INT UNSIGNED, auuidcolumn mapped asstring), so the package does not guess; where a route can carry such an ID, its parameter is constrained.dev-mainbranch alias are those of 1.5.0.Behavior changes for 1.4 users
Filter::related()with a dotted name was rejected as "a plain relation name" is required; it is a path now. An invalid name reports "A related filter requires a relation name or a dotted relation path."TypeErrorbecomesInvalidArgumentException, and "Unknown mapped relation" in a write becomes "Related filters and relation paths are supported only for read queries."Verification
examples/crud.php,translations.phpandrelations.phprun.BelongsTo,BelongsToManyand three relations, equal to the nested calls in value and SQL; the visibility of the last relation; criteria paths that start and end with a number; writes with a path or a related filter on an unknown relation. The two fix tests fail without the fixes.4.3.*).🤖 Generated with Claude Code