Skip to content

Fix Eloquent cast updates and inherited queue attributes - #88

Merged
binaryfire merged 8 commits into
0.4from
upstream-sync-2026-10-28-batch-8
Oct 29, 2026
Merged

binaryfire merged 8 commits into
0.4from
upstream-sync-2026-10-28-batch-8

Conversation

@binaryfire

@binaryfire binaryfire commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Laravel Updates

  • Preserve inherited queue attributes when a child uses Queueable and its corresponding property is null. Non-null child properties still take precedence.
  • Correct Eloquent JSON-path updates and cached accessors. Encrypted array and collection casts use their own encryption format, pending changes to cast objects survive JSON-path writes, and subsequent reads no longer return stale accessor values.
  • Add regression coverage for cached routes served from a subdirectory, including the root route and repeated slashes. The existing matcher already preserves the request's base URL correctly.
  • Reject invalid row-value comparison operators and quote literal cursor-order columns containing parentheses. Selected SQL expressions retain their expression behavior.

Additional Hypervel Fixes

  • Invalidate stale cached accessors after class casts, enum casts and legacy setters write a value. Setter-only attributes no longer retain input objects that can later overwrite changes to a class-cast object.
  • Preserve edits made to cached class-cast objects and paired accessors inside setters. Track the stored values each object read or last wrote so explicit replacements win without discarding edits to other columns. Partial setter responses retain the values of omitted columns. Plain and encrypted casts use the same rule, with no extra caster calls or snapshot copies on unchanged reads.
  • Refresh cached null and get-only accessor values when another setter changes their raw input, without invoking a setter for null or inferring dependencies on unrelated columns.
  • Preserve other attribute writes made by custom casters and Attribute setters. Evaluate their callbacks before merging the resulting values, so the merge uses the current attributes instead of an earlier snapshot.
  • Clear cached objects before synchronizing raw replacement attributes. Refreshing or repopulating a model can no longer write objects from its old row over the replacement values.
  • Compare encrypted class-cast values through the same encrypter used to store them, including key rotation. A separate model encrypter no longer causes dirty checks to fail or compare the wrong ciphertext.

The changes include the upstream regression tests and additional cases for the corrected behavior. Formatting, full static analysis, the database unit suite and affected SQLite integration tests pass. CI runs the supported database matrix. Source comments explain the changes that future upstream updates need to preserve.

Note

Fix stale cached Eloquent casts and inherited queue dispatch attributes

  • Reworks cast writeback in HasAttributes.php: cached class-cast objects and Attribute accessors now record a raw-attribute baseline, and setter results are merged against that baseline so edits made during setters and partial writebacks are preserved instead of lost or overwritten
  • Assigning raw values, enum casts, mutators, setRawAttributes(), discardChanges(), offsetUnset(), and serialization now invalidate the matching cached cast value and baseline, so cached objects no longer go stale or write back against replaced rows
  • Encrypted AsEncryptedArrayObject and AsEncryptedCollection casts now encrypt/decrypt via Crypt (not the model's primitive encrypter) for JSON-path updates, reads, and dirty checks, via the new isEncryptedClassCastable() predicate
  • Adds a bus dispatcher test confirming that Connection, Queue, and Delay attributes declared on a parent ShouldQueue class are inherited by queued child commands
  • Small fixes: Builder.whereRowValues() throws InvalidArgumentException on invalid operators, and ReadsClassAttributes.propertyOverridesAttribute() ignores null subclass properties
  • Risk: encrypted class-cast values previously stored with the model's primitive encrypter will not decrypt under Crypt in getArrayAttributeByKey() and originalIsEquivalent(); check existing rows written by the old path

Macroscope summarized 2bff3de.

Queueable declares nullable routing properties on the child class. Those defaults must not hide Connection, Queue or Delay attributes inherited from a parent. Ignore null properties when deciding whether a child property overrides an attribute, while retaining non-null overrides and cached reflection metadata.

Port laravel/framework#61826 from 1e3185debc2949e73d6d7fe3146bce09a8f127a6, reconciled against the recorded 13.x target 5d7797528723107cd4f495326838a7d7d67fbb20. Include the upstream parent/child dispatch regression with exact connection, queue and delay assertions.

Validation: the regression fails before the correction. The complete dispatcher test file, affected queue attribute consumers, formatting and full source, type-fixture and skeleton analysis pass.
JSON-path writes now merge pending object mutations before editing the stored value, use the correct encryption path for encrypted class casts, and clear stale accessor values afterward. Normal assignments also clear the accessor cache. Keep strict JSON handling and per-model cache ownership.

Reconcile laravel/framework#61834 (09991edb59), #61847 (297e6acacb), #61962 (f618f7911d) and #62035 (bff5d2a24e) together against 13.x target 5d7797528723107cd4f495326838a7d7d67fbb20. These changes share the same attribute write paths and regression files; include every applicable upstream test and assertion.

Correct related stale-cache paths through enum casts, custom class casts and both mutator forms. Invalidate after successful writes because callbacks can read and repopulate old values. Cache setter inputs only for attributes with getters, preventing a write-only input object from overwriting subsequent mutations to a class-cast object. Paired accessor and setter object retention remains intact.

Encrypted class-cast dirty checks now use Crypt for decryption and previous keys, matching the casts themselves. A separately configured model encrypter continues to serve primitive encrypted casts. This prevents MAC failures and incorrect key-rotation decisions when the two encrypters differ.

Validation: upstream and additional regressions reproduce the defects before correction. Complete model and encrypted-cast test files, affected Eloquent and casting integration tests on isolated SQLite, formatting and full source, type-fixture and skeleton analysis pass. Server-specific createOrFirst cases retain their existing driver requirements.
Cover root and nested route matching when the application is served below a URL prefix, including repeated trailing slashes. Preserve all request server metadata and assertions from laravel/framework#61794 (916931af14).

The compiled matcher already trims the request path without rewriting REQUEST_URI, so no source change is needed. These cases protect base-URL detection and the existing route-cache behavior.

Validation: the complete CompiledRouteCollectionTest passes, along with formatting and framework static analysis.
Integrate laravel/framework#61837, #61838, #61841 and #62131 from revisions 2c3294632c, 71cf667d43, a76d678087 and 6d0f491630. Reject invalid row-value operators, quote literal cursor columns correctly, retain union select and join bindings, and remove union page bounds from grouped pagination counts.

Correct related pagination defects at the query-builder boundary. Each union member resolves its own selected columns and expressions, nested unions receive the page conditions, and bindings are rebuilt in SQL order. Bounded selects and union groups keep their original row selection while paging filters the resulting rows. Reverse navigation changes the page ordering rather than the ordering that chooses bounded rows. Counts retain that ordering only when it affects membership.

Track the conditions and bindings owned by paging until scopes and query callbacks finish. This preserves normal Eloquent scope removal, eager loading, model cursor casts, direct page-builder identity, later ordering and limit changes, and caller-updated bindings. Clone shared union members and retire consumed markers so reusing a builder cannot apply old page filters again. Ordinary queries avoid normalized condition copies and unrelated nested-group clones.

Complete embedded callbacks before validating statement options or capturing bindings. Make property resets respect nullable and non-nullable types, and document the custom-driver hooks for embedding, row selection and aggregate ordering. Source comments explain the reasons for these differences.

Port all applicable upstream assertions and add regressions for compound aliases, nested and bounded unions, forward and backward iteration, quoted output aliases, current bindings, builder reuse and custom-driver isolation. Validation: formatting and full source, type-fixture and skeleton analysis pass; database unit tests and affected SQLite integration tests pass, as do cursor, binary and query-builder tests on isolated PostgreSQL, MySQL and MariaDB. The dependent custom-driver implementation and its analytical paging tests were also verified against this branch.
Bring in the latest queue cancellation, batch-failure reporting and SQS overflow handling fixes before publishing the database changes.

The incoming changes do not overlap the pagination, cast-cache or attribute-reader edits, and no merge resolutions or adaptations are required. The combined bus, queue driver and outbox test selection passes.
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 26 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between bd90ac5 and 2bff3de.

Files selected for processing: 3
  • src/database/src/Eloquent/Concerns/HasAttributes.php
  • src/database/src/Eloquent/Model.php
  • tests/Database/DatabaseEloquentModelTest.php

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 20d31e8 and bd90ac5.

Files selected for processing: 6
  • src/database/src/Concerns/BuildsQueries.php
  • src/database/src/Eloquent/Concerns/HasAttributes.php
  • src/database/src/Eloquent/Model.php
  • src/database/src/Query/Builder.php
  • tests/Database/DatabaseEloquentModelTest.php
  • tests/Database/DatabaseQueryBuilderTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The changes update Eloquent attribute and encrypted-cast handling, add validation for query conditions, refine inherited attribute resolution, and add coverage for queue dispatch and compiled routes.

Changes: Eloquent attribute caching and encrypted casts

Layer / File(s) Summary
Class-cast cache lifecycle and writeback
src/database/src/Eloquent/Concerns/HasAttributes.php, src/database/src/Eloquent/Model.php, tests/Database/DatabaseEloquentModelTest.php
Cached class casts track backing values and reconcile writeback with current attributes. Cache state is cleared when attributes are replaced, discarded, removed, or serialized. Tests cover mutable casts, backing columns, and raw replacement.
Mutator writes and accessor cache updates
src/database/src/Eloquent/Concerns/HasAttributes.php, tests/Database/DatabaseEloquentModelTest.php
Setter output is merged with current attributes, and related accessor caches are invalidated. Tests cover accessor refresh, setter side effects, and in-place cast edits.
JSON-path updates and encrypted class casts
src/database/src/Eloquent/Concerns/HasAttributes.php, tests/Database/DatabaseEloquentModelTest.php, tests/Integration/Database/EloquentModelEncryptedCastingTest.php
JSON-path operations handle encrypted array-object and collection casts. Encrypted-cast equivalence checks use Crypt. Tests cover JSON-path updates and rotating keys.

Query builder condition validation

Layer / File(s) Summary
Cursor column handling
src/database/src/Concerns/BuildsQueries.php, tests/Database/DatabaseQueryBuilderTest.php
Cursor conditions wrap a parenthesized original column only when it differs from the cursor column. Added coverage checks identifier wrapping and bindings.
Row-value operator validation
src/database/src/Query/Builder.php, tests/Database/DatabaseQueryBuilderTest.php
whereRowValues rejects unsupported operators before adding conditions or bindings. Added coverage checks rejection of an SQL-like operator.

Inherited class attributes

Layer / File(s) Summary
Inherited attribute resolution and dispatch
src/support/src/Traits/ReadsClassAttributes.php, tests/Bus/BusDispatcherTest.php
A subclass property overrides an inherited attribute only when it is non-null. A dispatch test checks inherited connection, queue, and delay attributes.

Compiled route matching coverage

Layer / File(s) Summary
Subdirectory and repeated-slash route cases
tests/Integration/Routing/CompiledRouteCollectionTest.php
Added cases for root and regular compiled routes requested beneath /app/, including repeated slashes.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Possibly related PRs

  • hypervel/components-backup#87: Both PRs modify cursor-condition behavior in BuildsQueries.php; their merged result depends on how the edits combine.
Merge Risk: Minimal · previous review bd90a

No change-related issue remains identified; the PR is mergeable after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly identifies the two main changes: Eloquent cast updates and inherited queue attributes. It is concise and specific.
Docstring Coverage Passed Docstring coverage is 85.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description clearly explains the bug fixes, affected behavior, regression coverage, and reported verification results. It does not explicitly select a contribution type, list exact verification co…
Full details: Docstring Coverage

Explanation

Docstring coverage is 85.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 20 functions across 10 files.

Full details: Description check

Explanation

The description clearly explains the bug fixes, affected behavior, regression coverage, and reported verification results. It does not explicitly select a contribution type, list exact verification commands, or complete the submission checklist, but it is otherwise substantially complete and relevant.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix union keyset pagination and Eloquent cast updates

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Preserve selected rows, bindings, and accurate counts across bounded and nested union pagination.
• Preserve pending cast changes and refresh stale Eloquent accessors after attribute writes.
• Fix inherited queue attributes and add regression coverage for cached routes and query validation.
Diagram

graph TD
  A["Paging APIs"] --> B["Scopes callbacks"] --> C["Keyset preparation"] --> D{"Bounded select?"}
  D -->|Yes| E["Derived table"] --> F["Page predicates"] --> G["Union members"] --> H["SQL bindings"]
  D -->|No| F
  F -->|No union| H
  G --> H
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Filter only the completed union
  • ➕ Simpler predicate placement and fewer member-specific column mappings.
  • ➖ Changes which rows survive bounded members and can alter UNION DISTINCT results.
  • ➖ May require a less portable wrapper around the complete union.

Recommendation: Keep member-aware keyset preparation: it preserves bounded members and resolves each member’s aliases and expressions. Review derived-table isolation and binding reconstruction closely, as those carry the principal portability risk.

Files changed (15) +1414 / -117

Bug fix (5) +555 / -111
BuildsQueries.phpDelegate cursor conditions to the base query builder +15/-71

Delegate cursor conditions to the base query builder

• Replaces inline union predicate construction with shared keyset preparation. Cursor values are resolved before query isolation so Eloquent casts remain effective.

src/database/src/Concerns/BuildsQueries.php

Builder.phpReverse union page order without reversing member selection +6/-2

Reverse union page order without reversing member selection

• Backward cursor navigation now reverses union ordering separately from the first SELECT’s ordering, preserving the rows chosen by a bounded first member.

src/database/src/Eloquent/Builder.php

HasAttributes.phpPreserve cast mutations and invalidate stale accessor caches +44/-13

Preserve cast mutations and invalidate stale accessor caches

• JSON-path writes merge pending cast-object changes and use the encryption format of encrypted class casts. Assignments through primitive, class, enum, and mutator paths clear stale caches; encrypted class-cast dirty checks use their own encrypter.

src/database/src/Eloquent/Concerns/HasAttributes.php

Builder.phpPrepare union keyset pages after callbacks and preserve count semantics +489/-25

Prepare union keyset pages after callbacks and preserve count semantics

• Adds shared, deferred keyset preparation for cursor and ID-based pages, including bounded SELECT isolation, recursive union filtering, member-specific columns, and binding reconstruction. Also fixes grouped-union counts, embedded-query callback timing, row-value operator validation, and typed property resets during cloning.

src/database/src/Query/Builder.php

ReadsClassAttributes.phpLet inherited attributes survive null child properties +1/-0

Let inherited attributes survive null child properties

• A child property overrides an inherited class attribute only when its initialized value is non-null.

src/support/src/Traits/ReadsClassAttributes.php

Tests (9) +856 / -5
BusDispatcherTest.phpTest inherited queue routing attributes +33/-0

Test inherited queue routing attributes

• Verifies that a Queueable child retains its parent’s connection, queue, and delay attributes during dispatch.

tests/Bus/BusDispatcherTest.php

DatabaseEloquentModelTest.phpCover JSON-path cast updates and accessor cache invalidation +217/-0

Cover JSON-path cast updates and accessor cache invalidation

• Tests pending cast-object mutations, refreshed accessors, enum and class-cast assignments, legacy and modern setters, and setter-only cache ownership.

tests/Database/DatabaseEloquentModelTest.php

DatabaseQueryBuilderEmbeddingTest.phpAlign embedding override with callback preparation +3/-3

Align embedding override with callback preparation

• Renames the test builder’s override to the embedding preparation hook while retaining parent callback and timeout behavior.

tests/Database/DatabaseQueryBuilderEmbeddingTest.php

DatabaseQueryBuilderPaginationTest.phpExercise shared union keyset iteration and direct pages +86/-0

Exercise shared union keyset iteration and direct pages

• Checks ascending and descending chunk and lazy iteration across union aliases. Direct-page tests cover late scope removal, bounded selections, reused builders, counts, and binding changes.

tests/Database/DatabaseQueryBuilderPaginationTest.php

DatabaseQueryBuilderTest.phpCover union SQL, bindings, counts, and query validation +258/-2

Cover union SQL, bindings, counts, and query validation

• Adds SQL and binding assertions for grouped counts, nested unions, selected expressions, joins, custom isolation, and cursor-column quoting. Also covers embedding callbacks, invalid row operators, and nullable versus non-nullable clone resets.

tests/Database/DatabaseQueryBuilderTest.php

EloquentCursorPaginateTest.phpVerify bounded-union cursor pages against a database +115/-0

Verify bounded-union cursor pages against a database

• Checks forward and backward pages when the first SELECT, a member, or a nested union group is bounded. Also verifies Eloquent scopes, eager loading, implicit projections, and ordinary page limits.

tests/Integration/Database/EloquentCursorPaginateTest.php

EloquentModelEncryptedCastingTest.phpVerify encrypted class-cast JSON writes and dirty checks +88/-0

Verify encrypted class-cast JSON writes and dirty checks

• Tests JSON-path updates for encrypted array and collection casts. Dirty-check cases distinguish the class cast’s encrypter from the model encrypter, including key rotation.

tests/Integration/Database/EloquentModelEncryptedCastingTest.php

QueryBuilderTest.phpVerify grouped-union counts ignore page limits +9/-0

Verify grouped-union counts ignore page limits

• Confirms a grouped union’s pagination count includes the full result despite a union page limit.

tests/Integration/Database/QueryBuilderTest.php

CompiledRouteCollectionTest.phpCover cached routes beneath a subdirectory +47/-0

Cover cached routes beneath a subdirectory

• Adds regression cases for root and nested cached routes served from a subdirectory, including repeated and trailing slashes.

tests/Integration/Routing/CompiledRouteCollectionTest.php

Documentation (1) +3 / -1
database.mdDocument query embedding and paging extension hooks +3/-1

Document query embedding and paging extension hooks

• Documents the renamed embedding hook and how custom drivers preserve row-limiting clauses and aggregate ordering during keyset pagination.

src/docs/database.md

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Union pages fail with qualified aliases ✓ Resolved
Description
getKeysetOutputColumn() does not map an unqualified paging column such as id to the output alias
of a selection such as posts.id as value. When another union member selects `archives.archive_id
as value, its paging predicate is consequently rebound to id rather than archives.archive_id`,
yielding invalid SQL if that member has no id column.
Code

src/database/src/Query/Builder.php[R3565-3571]

+                if ($parameter === $alias || $parameter === $original) {
+                    return $alias;
+                }
+            }
+        }
+
+        return Str::afterLast($parameter, '.');
Evidence
The new output-column resolver compares id only with the full posts.id expression and value,
then falls back to id. The new union path passes that normalized name to every member; the
original-column resolver requires an alias match to recover archives.archive_id.

src/database/src/Query/Builder.php[3538-3571]
src/database/src/Query/Builder.php[3476-3487]
src/database/src/Query/Builder.php[3619-3635]
src/database/src/Concerns/BuildsQueries.php[549-567]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Union keyset paging loses the shared output alias when the caller names an unqualified source column selected with a qualified name.
## Fix Focus Areas
- src/database/src/Query/Builder.php[3555-3571]
- src/database/src/Query/Builder.php[3619-3635]
## Recommended Fix
When resolving a paging column against a selected alias, also recognize an unambiguous unqualified source-column match. Normalize the predicate to the output alias before rebinding it against each union member, and add a regression with differently named source columns.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Union pages fail after custom ID ordering ⊘ Outdated
Description
removeOrdersFor() filters matching orders but never updates its by-reference $bindings argument,
despite callers passing the live order or unionOrder bindings array. When inOrderOf('id', [1])
precedes forPageAfterId(..., 'id'), the union order is removed while its binding remains and is
still flattened for execution.
Code

src/database/src/Query/Builder.php[R2820-2821]

+        if ($this->unions) {
+            $this->unionOrders = $this->removeOrdersFor($this->unionOrders ?? [], $this->bindings['unionOrder'], $orderColumn);
Evidence
inOrderOf() adds a bound union order, and the union paging call removes the order for the paging
column. Although removeOrdersFor() receives the live bindings array by reference, its body only
filters $orders; union SQL therefore compiles without the removed order while execution still
includes its binding. The same unused parameter is also passed by the non-union order-removal call
site.

src/database/src/Query/Builder.php[2663-2689]
src/database/src/Query/Builder.php[2816-2834]
src/database/src/Query/Builder.php[2883-2891]
src/database/src/Query/Grammars/Grammar.php[981-998]
src/database/src/Query/Builder.php[4644-4647]
src/database/src/Query/Builder.php[2878-2892]
src/database/src/Query/Builder.php[2778-2787]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ID-based union paging can discard a matching bound ordering clause without discarding its binding. `removeOrdersFor()` accepts live bindings by reference but does not update them.
## Fix Focus Areas
- src/database/src/Query/Builder.php[2782-2786]
- src/database/src/Query/Builder.php[2820-2824]
- src/database/src/Query/Builder.php[2878-2892]
## Recommended Fix
Update order removal so it removes exactly the bindings owned by discarded orders while preserving bindings for retained orders. Check the callers that pass `order` and `unionOrder` bindings, and add a union regression combining `inOrderOf()` on the paging column with `forPageAfterId()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/database/src/Query/Builder.php Outdated
Comment thread src/database/src/Query/Builder.php Outdated
Remove the coupled union pagination, count, query preparation and embedding changes from this branch so they can be completed together in a dedicated change. Restore the previous query-builder implementation, corresponding tests and driver documentation.

Keep the independent Laravel #61837 and #61838 fixes: quote literal cursor columns containing parentheses and reject invalid row-value operators. Their complete regression tests remain in this branch.

Validated the restored query-builder, embedding, pagination and integration test files, the Database suite, formatting and full static analysis.
Clearing every class-cast cache entry after a mutator loses edits made to the cached object inside that mutator. Keeping every entry instead allows an old object to overwrite replacement values. Track the values each cached object read or last wrote, and compare only its backing columns during writeback.

Explicit replacements take precedence for their columns while pending object edits to other columns survive. Discard the obsolete object after merging the remaining writes. Keep the record on the model instance and clear it wherever the object cache is cleared; no additional caster calls are needed.

Evaluate caster and Attribute callbacks before merging the current attributes so their other writes and encrypted-cast synchronizations are retained. Clear caches before synchronizing raw replacement attributes, preventing objects from the previous row from overwriting the replacement.

Regression coverage includes both setter styles, encrypted and plain casts, held object references, partial backing-column replacements, reads and edits within setters, raw-row replacement, and callback side effects. Formatting, full static analysis, the Database suite and affected Eloquent integration tests pass.
@binaryfire binaryfire changed the title Fix database pagination and Eloquent cast updates Fix Eloquent cast updates and inherited queue attributes Oct 29, 2026
@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

A cached Attribute value could overwrite a raw column updated by another setter. Apply the same backing-value comparison used for class casts through one shared writeback helper. Explicit replacements win while pending edits to other columns survive.

Validate cached null and get-only values against their own raw input without invoking a setter or inferring dependencies on other attributes. Preserve normal same-key invalidation and caching flags, and clear the new per-model records with their cache entries.

Keep baseline values for columns omitted by partial setter responses, including when an object is first assigned. Update only entries whose values changed so unchanged reads do not copy the shared snapshot.

Regression coverage includes sibling setter writes, cached nulls, paired multi-column accessors and partial responses after reads and assignments. Formatting, full static analysis, affected database suites and focused model and casting checks pass.
@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai The contribution-template check does not apply to this maintainer-directed change, as stated at the beginning of AGENTS.md. The description covers the final changes and validation.

@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
head -n 180 AGENTS.md

Length of output: 19717


@binaryfire You are correct. The opening of AGENTS.md explicitly exempts maintainer-directed work from the external contribution requirements. I withdraw the contribution-template concern.

The description covers the final changes and reported validation. No contribution-template changes are needed for this PR.


🧠 Learnings used
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-10T12:24:15.571Z
Learning: In `src/api-client`, `PendingRequest` is intentionally a mutable, single-operation Laravel-style builder. Concurrent reuse of one pending-request instance is unsupported, and reviews should not require locks, context slots, or parallel lifecycle channels for that use case.
Learnt from: CR
Repo: hypervel/components-backup PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-09-08T21:31:34.455Z
Learning: Always run framework commands from the repository root.
Learnt from: CR
Repo: hypervel/components-backup PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-09-08T21:31:34.455Z
Learning: **Read the source before describing behavior** — never state how code behaves from memory or Laravel assumptions.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 9
File: src/boost/docs/migrations.md:1660-1664
Timestamp: 2026-08-09T23:43:44.565Z
Learning: In Markdown documentation, separate consecutive GitHub Flavored Markdown alert blocks such as `> [!NOTE]` and `> [!WARNING]` with a blank line. Without the separator, GitHub renders the later alert marker as literal text within the preceding alert block. The repository uses this pattern in `src/boost/docs/migrations.md`, `aop.md`, and `artisan.md`; markdownlint rule MD028 is not enforced.
Learnt from: CR
Repo: hypervel/components-backup PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-09-08T21:31:34.455Z
Learning: **Never use subagents without explicit user consent** — Do not spawn or delegate work to subagents unless the user explicitly requests or approves their use.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T18:47:57.777Z
Learning: For this Hypervel codebase, changed production methods follow the project method-documentation convention. Descriptive test method names do not require boilerplate docblocks.
Learnt from: CR
Repo: hypervel/components-backup PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-09-08T21:31:34.455Z
Learning: **Avoid bulk modification tools** — tools like `sed` and `replace_all` often have unwanted side effects. Never use bulk modification tools without explicit user approval; prefer manual edits.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-09T04:52:17.684Z
Learning: In `tests/Console/ArtisanCommandTest.php`, the `PendingCommandDdFixture` directory intentionally uses mode `0755`. It is not writable by other users and contains only an inert execution counter, so changing its mode does not improve correctness or meaningful security.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 11
File: src/api-client/src/PendingRequest.php:314-387
Timestamp: 2026-08-10T12:24:01.065Z
Learning: In the PHP API Client package, `Hypervel\ApiClient\PendingRequest` is a mutable Laravel-style builder that belongs to one operation. Concurrent reuse of the same `PendingRequest` instance is unsupported and documented in the public guide. Normal `Hypervel\ApiClient\ApiClient` forwarding creates a fresh `PendingRequest` for every call, so supported concurrent API client operations are isolated.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-09T12:55:36.087Z
Learning: In `src/testbench/src/Concerns/HandlesRoutes.php`, application reload clears after-created callbacks. Reset `$syncTestbenchRoutesHasRun` in the reload `finally` block so later uncached route definitions register replacement synchronization callbacks. Do not use a per-file callback registry.
Learnt from: CR
Repo: hypervel/components-backup PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-09-08T21:31:19.636Z
Learning: Applies to AGENTS.md : Read and follow ./AGENTS.md. It is the authoritative instruction file for this repo.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-09T03:52:55.969Z
Learning: In this repository, `AGENTS.md` defines `phpstan.types.neon.dist` as a configuration for only the committed `types/` fixtures. Do not pass source or test paths to this configuration during PHPStan validation.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T15:06:36.109Z
Learning: Repository documentation policy favors PHPDoc and comments that explain useful contracts or rationale. Do not add class or member-inventory documentation solely to increase docstring coverage.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 4
File: docs/plans/2026-08-08-1443-telescope-correctness-current-parity-and-watcher-lifecycles.md:572-572
Timestamp: 2026-08-08T20:33:02.925Z
Learning: In `docs/plans/2026-08-08-1443-telescope-correctness-current-parity-and-watcher-lifecycles.md`, the code span ` nonce="..."` intentionally includes a leading space because it documents an HTML attribute fragment. Do not remove that whitespace for Markdownlint MD038. The repository does not run Markdownlint.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 87
File: src/database/src/Eloquent/Relations/HasOneOrMany.php:0-0
Timestamp: 2026-10-28T22:13:01.264Z
Learning: Within repository "hypervel/components-backup", only for files matching one of ["src/database/src/Eloquent/Relations/HasOneOrMany.php"]: When reviewing changes to HasOneOrMany::forceCreate(), check that the relationship foreign key is filled before pending attributes, because pending-attribute mutators can read that key. Preserve the relationship foreign key over conflicting pending attributes and caller values.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 4
File: src/telescope/src/Storage/EntryQueryOptions.php:29-34
Timestamp: 2026-08-08T20:33:07.401Z
Learning: In `src/telescope/src/Storage/EntryQueryOptions.php`, `EntryQueryOptions::fromRequest()` does not implement a request-validation error boundary. It forwards raw Telescope dashboard request values to typed setters for `batchId`, `uuids`, `beforeSequence`, `tag`, and `familyHash`. Do not request validation for only `uuids` or `beforeSequence` unless the shared boundary contract is changed consistently.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-09T03:52:55.969Z
Learning: In `tests/Testing/Console/TestCommandTest.php`, the signal-path regression test is intentionally unconditional because the root package requires both `ext-pcntl` and `ext-posix`.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T00:44:21.111Z
Learning: In the Hypervel Image component, tests for `Hypervel\Image\Image::store()`, `storeAs()`, `storePublicly()`, and `storePubliclyAs()` must assert the options passed to the filesystem `put()` boundary. Do not use a local Flysystem adapter `getVisibility()` result to verify the public-visibility override, because an ordinary local write can report public visibility.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 7
File: src/wayfinder/src/TypeScript.php:121-126
Timestamp: 2026-08-09T12:54:02.766Z
Learning: Hypervel supports Swoole on Linux. The repository `.gitattributes` file forces LF line endings for every checkout. In `src/wayfinder/src/TypeScript.php`, `TypeScript::cleanUp()` can rely on `PHP_EOL` and generated input both using LF in supported environments.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T15:06:36.109Z
Learning: In `src/testbench/src/Bootstrapper.php`, orphaned Swoole serve-master ownership is verified with the live PID, orphan status, the runtime `storage/framework/hypervel.pid` file, and the recorded process-start identity. Do not add command-line matching because Swoole can change the serve-master process title after startup.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-09T04:52:17.684Z
Learning: For any Hypervel test that needs an isolated scratch directory, use `Hypervel\Testing\ParallelTesting::tempDir('TestName')` regardless of the base test class. For writable reusable fixtures, remove any prior directory before setup and clean it up afterward. Use a unique path with complete local cleanup when a fixture intentionally becomes read-only.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T00:44:21.111Z
Learning: In `src/image/src/ImageManager.php`, `ImageManager::fromPath()` is intentionally lazy and delegates to the concrete `Filesystem::get(string $path): string` contract, which returns string contents or throws `FileNotFoundException`. Only `ImageManager::fromStorage()` handles a nullable disk-read result.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 15
File: src/image/src/Drivers/InterventionDriver.php:86-90
Timestamp: 2026-08-12T20:39:24.839Z
Learning: In `src/image/src/Drivers/InterventionDriver.php`, Hypervel `HandleExceptions::handleError()` converts an unsuppressed libmagic `E_WARNING` from `finfo::buffer()` into an `ErrorException` before `finfo::buffer()` can return `false`. Do not recommend a `false`-return branch for this call unless error handling or suppression changes.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 14
File: src/foundation/src/Http/Traits/HasCasts.php:388-390
Timestamp: 2026-08-12T02:15:16.849Z
Learning: In `src/foundation/src/Http/Traits/HasCasts.php`, `HasCasts` is a Hypervel-owned request-casting trait and not a Laravel `FormRequest` extension surface. Do not treat unused protected helpers in this trait, such as the removed `asJson`, as compatibility APIs without source, test, or documented contract evidence.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 4
File: docs/plans/2026-08-08-1443-telescope-correctness-current-parity-and-watcher-lifecycles.md:228-228
Timestamp: 2026-08-08T20:33:01.015Z
Learning: In `docs/plans/2026-08-08-1443-telescope-correctness-current-parity-and-watcher-lifecycles.md`, the phrase `EntryQueryOptions` “tor retrieve” typos intentionally quotes the original misspelling as audit evidence. Do not replace the quoted text with “to retrieve,” because that would make the correction record inaccurate.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-12T02:16:31.945Z
Learning: For Hypervel Eloquent casts, `Hypervel\Database\Eloquent\Casts\Json` follows Laravel-style encoder semantics and returns `string|false`. Callers must use an exact `false` check to distinguish JSON encoding failure for both native and custom codecs.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 14
File: src/database/src/Eloquent/Casts/AsArrayObject.php:35-41
Timestamp: 2026-08-12T02:15:07.824Z
Learning: In `src/database/src/Eloquent/Casts/Json.php`, `Json::encode()` intentionally preserves the Laravel-style `string|false` encoder contract. Eloquent cast setters, including `AsArrayObject`, must use an exact `false` check and throw `JsonEncodingException::forAttribute($model, $key, json_last_error_msg())` to retain model and attribute context. Custom encoders are unconstrained and use `false` as the shared failure signal; do not replace this with `JsonException` handling based on `Hypervel\Support\Json`.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 8
File: tests/Integration/Database/Sqlite/DatabaseSchemaBlueprintTest.php:560-608
Timestamp: 2026-08-09T15:35:26.954Z
Learning: In `tests/Integration/Database/Sqlite/DatabaseSchemaBlueprintTest.php`, `testRebuildPreservesStrictTables()` requires `#[RequiresDatabase('sqlite', '>=3.37.0')]` because SQLite STRICT tables were added in SQLite 3.37.0. `testRebuildPreservesWithoutRowid()` does not require that guard: WITHOUT ROWID was added in SQLite 3.8.2, and the SQLite schema rebuild path already requires SQLite 3.26 through `pragma_table_xinfo`. Use `sqlite_master` rather than `pragma_table_list` when verifying WITHOUT ROWID behavior on this baseline.
Learnt from: binaryfire
Repo: hypervel/components-backup PR: 0
File: :0-0
Timestamp: 2026-08-13T15:06:36.109Z
Learning: In `tests/Integration/Database/QueryBuilderTest.php`, the `fetch_values` table is created as a test-local fixture. Database integration tests rebuild the schema before each test, so selectively dropping this fixture is unnecessary and inconsistent with the test lifecycle.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@binaryfire
binaryfire merged commit 8f49de7 into 0.4 Oct 29, 2026
46 checks passed
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

Successfully merging this pull request may close these issues.

1 participant