-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add ToArray functionality for flattening Input objects #9
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
Conversation
- Add ToArrayInterface for converting Input objects to flat arrays - Add ToArray implementation with recursive object flattening - Handle property name conflicts (later values overwrite earlier ones) - Preserve arrays for SQL IN clause compatibility - Ignore private/protected properties (public only) - Add comprehensive test suite covering all edge cases This enables SQL parameter binding from nested Input objects: $params = $toArray($orderInput); // Flat array for SQL queries 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Reviewer's GuideThis PR introduces a new Class diagram for ToArray and ToArrayInterfaceclassDiagram
class ToArrayInterface {
<<interface>>
+__invoke(object $input): array
}
class ToArray {
+__invoke(object $input): array
-extractProperties(object $object): array
}
ToArray ..|> ToArrayInterface
Flow diagram for recursive flattening in ToArrayflowchart TD
A[Input object] --> B{Public property?}
B -- No --> C[Skip property]
B -- Yes --> D{Is object?}
D -- Yes --> E[Recursively extract properties]
D -- No --> F{Is array?}
F -- Yes --> G[Preserve array]
F -- No --> H[Add scalar value]
E --> I[Add extracted properties to result]
G --> I
H --> I
I --> J[Return flat associative array]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughA new Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ToArray
participant InputObject
Client->>ToArray: __invoke(InputObject)
ToArray->>InputObject: Inspect public properties
alt Property is object
ToArray->>ToArray: Recursively extract properties
else Property is array or scalar
ToArray->>ToArray: Include as-is
end
ToArray-->>Client: Return flat associative array
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @koriym - I've reviewed your changes - here's some feedback:
- extractProperties currently serializes all public properties; consider filtering by the #[Input] attribute so only explicitly annotated fields are flattened.
- Right now objects nested inside arrays are kept intact; you may want to recursively flatten Input objects within arrays as well for consistency.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- extractProperties currently serializes all public properties; consider filtering by the #[Input] attribute so only explicitly annotated fields are flattened.
- Right now objects nested inside arrays are kept intact; you may want to recursively flatten Input objects within arrays as well for consistency.
## Individual Comments
### Comment 1
<location> `src/ToArray.php:47` </location>
<code_context>
+ continue;
+ }
+
+ // Keep arrays and scalar values as-is
+ /** @psalm-suppress MixedAssignment */
+ $result[$name] = $value;
</code_context>
<issue_to_address>
Arrays containing objects are not recursively processed.
Arrays of objects are not deeply converted; further logic is required for recursive conversion if needed.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
// Keep arrays and scalar values as-is
/** @psalm-suppress MixedAssignment */
$result[$name] = $value;
=======
// Recursively process arrays of objects
if (is_array($value)) {
$processedArray = [];
foreach ($value as $k => $v) {
if (is_object($v)) {
$processedArray[$k] = $this->extractProperties($v);
} else {
$processedArray[$k] = $v;
}
}
/** @psalm-suppress MixedAssignment */
$result[$name] = $processedArray;
} else {
// Keep scalar values as-is
/** @psalm-suppress MixedAssignment */
$result[$name] = $value;
}
>>>>>>> REPLACE
</suggested_fix>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
tests/ToArrayTest.php (1)
36-77: Remove unused variable.The
$authorvariable on line 38 is declared but never used, making it dead code.- $author = new class { - public function __construct( - #[Input] - public readonly string $name = 'John', - #[Input] - public readonly string $email = 'john@example.com', - ) { - } - }; -
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/ToArray.php(1 hunks)src/ToArrayInterface.php(1 hunks)tests/ToArrayTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
src/ToArrayInterface.php (3)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : Every parameter sourced from query data must have the #[Input] attribute.
src/ToArray.php (1)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
tests/ToArrayTest.php (4)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : Every parameter sourced from query data must have the #[Input] attribute.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : The #[Input] attribute must be applied to parameters, not classes.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/Attribute/Input.php : Attribute class Input must be defined as #[Attribute(Attribute::TARGET_PARAMETER)] in src/Attribute/Input.php.
🧬 Code Graph Analysis (1)
src/ToArray.php (2)
src/InputQuery.php (1)
InputQuery(70-506)src/ToArrayInterface.php (1)
__invoke(16-16)
🪛 PHPMD (2.15.0)
tests/ToArrayTest.php
24-24: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
26-26: Avoid unused parameters such as '$age'. (Unused Code Rules)
(UnusedFormalParameter)
38-38: Avoid unused local variables such as '$author'. (Unused Code Rules)
(UnusedLocalVariable)
61-61: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
63-63: Avoid unused parameters such as '$email'. (Unused Code Rules)
(UnusedFormalParameter)
85-85: Avoid unused parameters such as '$status'. (Unused Code Rules)
(UnusedFormalParameter)
87-87: Avoid unused parameters such as '$userIds'. (Unused Code Rules)
(UnusedFormalParameter)
115-115: Avoid unused parameters such as '$id'. (Unused Code Rules)
(UnusedFormalParameter)
117-117: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
138-138: Avoid unused parameters such as '$public'. (Unused Code Rules)
(UnusedFormalParameter)
140-140: Avoid unused parameters such as '$private'. (Unused Code Rules)
(UnusedFormalParameter)
156-156: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
158-158: Avoid unused parameters such as '$email'. (Unused Code Rules)
(UnusedFormalParameter)
160-160: Avoid unused parameters such as '$address'. (Unused Code Rules)
(UnusedFormalParameter)
🔇 Additional comments (10)
src/ToArrayInterface.php (1)
7-17: LGTM! Clean interface design with clear documentation.The interface is well-structured with appropriate type declarations and comprehensive documentation. The method signature clearly conveys the intent and return type.
src/ToArray.php (2)
13-22: LGTM! Correct implementation of the interface.The class properly implements
ToArrayInterfacewith the#[Override]attribute and delegates to the private extraction method.
24-53: LGTM! Robust recursive property extraction with intentional conflict resolution.The implementation correctly:
- Uses reflection to access only public properties
- Recursively flattens nested objects
- Preserves arrays and scalar values as-is
- Handles property name conflicts by allowing nested properties to overwrite parent properties (as demonstrated in the test cases)
The recursive approach effectively flattens hierarchical Input structures for SQL parameter binding as intended.
tests/ToArrayTest.php (7)
10-17: LGTM! Proper test setup with dependency injection.The test class follows good practices with proper setup and type-hinted dependencies.
19-34: LGTM! Comprehensive test for simple object conversion.The test correctly validates basic object-to-array conversion with readonly properties and
#[Input]attributes.
48-77: LGTM! Excellent test for nested object flattening.The test correctly validates that nested objects are recursively flattened into a single-level array, which is the core functionality of this feature.
79-98: LGTM! Important test for array preservation.This test correctly validates that arrays are preserved as-is, which is crucial for SQL IN clause compatibility as mentioned in the PR objectives.
100-131: LGTM! Critical test for property name conflict resolution.This test correctly validates the intentional behavior where nested properties overwrite parent properties with the same name. The comment clearly explains the expected behavior.
133-149: LGTM! Important test for access control.This test correctly validates that private properties are ignored, ensuring proper encapsulation and access control.
151-172: LGTM! Proper handling of null values.This test correctly validates that null values are preserved in the output array, which is important for nullable database columns.
- Add intuitive Quick Example showing query string → hierarchical objects - Replace complex overview with simple, immediate value demonstration - Move Demo section to end (logical flow: learn → understand → try) - Remove unnecessary PSR-7 example, focus on simple $_POST usage - Add comprehensive ToArray documentation with Aura.Sql integration - Update CHANGELOG for v0.2.0 release with ToArray functionality The README now answers "what is this?" in 3 seconds with concrete examples. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
CHANGELOG.md (2)
10-12: Grammar & clarity tweak for the bullet point
The phrase reads awkwardly and currently implies two separate entities when only one implementation exists.- - `ToArrayInterface` and `ToArray` implementation for flattening objects to flat associative arrays + - `ToArrayInterface` and a `ToArray` implementation for flattening objects into flat associative arrays
45-45: Missing backlink for the new release tag
Every version section should have its reference link at the bottom to keep navigation consistent.[0.1.0]: https://github.com/ray-di/Ray.InputQuery/releases/tag/0.1.0 +[0.2.0]: https://github.com/ray-di/Ray.InputQuery/releases/tag/0.2.0README.md (3)
12-15: Code snippet is missing theInputimport
Without the import the snippet will not compile as-is and may confuse new users.-// HTTP Request: ?name=John&email=john@example.com&addressStreet=123 Main St&addressCity=Tokyo +use Ray\InputQuery\Attribute\Input; + +// HTTP Request: ?name=John&email=john@example.com&addressStreet=123 Main St&addressCity=Tokyo
30-33: Undefined$inputQueryin quick example
Showing instantiation (or at least a short comment) prevents readers from wondering where the variable comes from.
Even a single-line comment like// assume $inputQuery is an InputQuery instancewould suffice.
549-551: Typo in section heading – double “¥” characters-### SQL Param¥¥eter Binding +### SQL Parameter Binding
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
CHANGELOG.md(2 hunks)README.md(2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
README.md (10)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : Every parameter sourced from query data must have the #[Input] attribute.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters without #[Input], resolve them from the DI container, supporting #[Named] for scalar DI values.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : Parameters without #[Input] that can't be resolved by DI: use parameter default or throw exception.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : Parameters with #[Input] but missing from query: use parameter default or null if allowed.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : Convert all query keys to camelCase, handling snake_case, kebab-case, and PascalCase.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : The #[Input] attribute must be applied to parameters, not classes.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : Implement a reasonable recursion depth limit (e.g., 10 levels) to prevent infinite recursion in nested input resolution.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/Attribute/Input.php : Attribute class Input must be defined as #[Attribute(Attribute::TARGET_PARAMETER)] in src/Attribute/Input.php.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
CHANGELOG.md (1)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : Every parameter sourced from query data must have the #[Input] attribute.
🪛 LanguageTool
CHANGELOG.md
[uncategorized] ~11-~11: “and” (in addition to, following this) seems less likely than “a”.
Context: ...5-07-07 ### Added - ToArrayInterface and ToArray implementation for flattening...
(AI_HYDRA_LEO_CP_AND_AN)
Remove unused variable in testNestedObject method. The test creates the author object directly in the constructor instead. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
tests/ToArrayTest.php (1)
1-163: Consider adding tests for additional edge cases.While the current test coverage is comprehensive for the main use cases, consider adding tests for:
- Empty objects with no
#[Input]properties- Deeply nested objects (3+ levels)
- Objects with mixed annotated/non-annotated properties
- Performance characteristics with large nested structures
Would you like me to help generate additional edge case tests to further strengthen the test suite?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/ToArrayTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
tests/ToArrayTest.php (4)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : Every parameter sourced from query data must have the #[Input] attribute.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/InputQuery.php : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/**/*.php : The #[Input] attribute must be applied to parameters, not classes.
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Applies to docs/src/Attribute/Input.php : Attribute class Input must be defined as #[Attribute(Attribute::TARGET_PARAMETER)] in src/Attribute/Input.php.
🪛 PHPMD (2.15.0)
tests/ToArrayTest.php
24-24: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
26-26: Avoid unused parameters such as '$age'. (Unused Code Rules)
(UnusedFormalParameter)
51-51: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
53-53: Avoid unused parameters such as '$email'. (Unused Code Rules)
(UnusedFormalParameter)
75-75: Avoid unused parameters such as '$status'. (Unused Code Rules)
(UnusedFormalParameter)
77-77: Avoid unused parameters such as '$userIds'. (Unused Code Rules)
(UnusedFormalParameter)
105-105: Avoid unused parameters such as '$id'. (Unused Code Rules)
(UnusedFormalParameter)
107-107: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
128-128: Avoid unused parameters such as '$public'. (Unused Code Rules)
(UnusedFormalParameter)
130-130: Avoid unused parameters such as '$private'. (Unused Code Rules)
(UnusedFormalParameter)
146-146: Avoid unused parameters such as '$name'. (Unused Code Rules)
(UnusedFormalParameter)
148-148: Avoid unused parameters such as '$email'. (Unused Code Rules)
(UnusedFormalParameter)
150-150: Avoid unused parameters such as '$address'. (Unused Code Rules)
(UnusedFormalParameter)
🔇 Additional comments (7)
tests/ToArrayTest.php (7)
1-17: LGTM: Well-structured test setup.The test class is properly structured with appropriate namespace, imports, and dependency injection setup. The use of the
ToArrayInterfacetype hint ensures the tests work against the contract rather than the concrete implementation.
19-34: LGTM: Comprehensive test for simple object conversion.The test correctly verifies that a simple object with
#[Input]annotated properties is converted to a flat associative array. The use of constructor property promotion with readonly properties is a good practice.
36-67: LGTM: Excellent test for nested object flattening.This test effectively demonstrates the core functionality of flattening nested objects into a single associative array. The nested
authorobject properties are correctly merged into the top-level array, which aligns with the PR objectives for SQL parameter binding.
69-88: LGTM: Proper validation of array property preservation.The test correctly verifies that array properties are preserved as-is rather than being flattened, which is essential for SQL IN clause compatibility as mentioned in the PR objectives.
90-121: LGTM: Critical test for property name conflict resolution.This test validates the important behavior where later properties overwrite earlier ones when property names conflict. The comment on line 116 clearly documents this expected behavior, which is crucial for users to understand.
123-139: LGTM: Important test for access control validation.This test ensures that private properties are correctly ignored even when annotated with
#[Input], maintaining proper encapsulation. The use ofassertArrayNotHasKeyprovides clear negative validation.
141-162: LGTM: Thorough test for null value handling.The test correctly validates that null values are preserved in the output array, which is important for SQL parameter binding where null values have semantic meaning.
Summary
ToArrayInterfaceandToArrayimplementation for converting nested Input objects to flat associative arraysKey Features
Usage Example
Test Coverage
🤖 Generated with Claude Code
Summary by Sourcery
Implement ToArray functionality for flattening hierarchical Input objects into flat arrays with correct conflict resolution, array preservation, and public property filtering to support SQL parameter binding.
New Features:
Enhancements:
Tests:
Summary by CodeRabbit
New Features
Tests
Documentation