feat: improve API with newInstance method and optional FileUploadFactory#7
feat: improve API with newInstance method and optional FileUploadFactory#7
Conversation
- Rename create() to newInstance() for clearer method naming - Make FileUploadFactory optional with automatic default instantiation - Update README with comprehensive DI examples and newInstance usage - Fix syntax errors in documentation - Update tests and framework integration examples 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Reviewer's GuideThis PR overhauls the input creation API by renaming the core method, simplifying file upload factory setup, updating all usage sites and tests, enriching documentation with new DI examples, and adding a comprehensive CSV demo module to illustrate advanced usage patterns. Class diagram for InputQuery API changesclassDiagram
class InputQueryInterface {
+getArguments(ReflectionMethod method, array query): array
-create(string class, array query): object
+newInstance(string class, array query): object
}
class InputQuery {
-InjectorInterface injector
-FileUploadFactoryInterface|null fileUploadFactory
+__construct(InjectorInterface injector, FileUploadFactoryInterface|null fileUploadFactory = null)
+newInstance(string class, array query): object
+getArguments(ReflectionMethod method, array query): array
}
InputQueryInterface <|.. InputQuery
InputQuery o-- FileUploadFactoryInterface
class FileUploadFactoryInterface
class FileUploadFactory
FileUploadFactoryInterface <|.. FileUploadFactory
Class diagram for new CSV demo domain typesclassDiagram
class CsvDemo {
+process(FileUpload csvFile, string delimiter, bool hasHeader, string encoding, bool skipEmptyRows): array
+dump(string name, string email, int age, string role, AgeGroup ageGroup): void
+dump2(UserInput user, int email, AgeGroup ageGroup): void
}
class UserInput {
+__construct(string name, string email, int age, AgeInput ageInput, bool isActive = true, AgeGroup ageGroup = null)
+__toString(): string
+name: string
+email: string
+age: int
+ageInput: AgeInput
+isActive: bool
-ageGroup: AgeGroup
}
class AgeInput {
+__construct(int age)
+age: int
}
class AgeGroup {
+addAge(?int age): void
+getGroups(): array
+getTotalCount(): int
-groups: array
}
CsvDemo o-- UserInput
UserInput o-- AgeInput
UserInput o-- AgeGroup
CsvDemo o-- AgeGroup
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughThis update introduces a broad renaming of the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant InputQuery
participant InputObject
participant FileUploadFactory (optional)
participant ServiceContainer (optional)
User->>InputQuery: newInstance(ClassName, inputData)
InputQuery->>FileUploadFactory: (if file upload detected)
InputQuery->>ServiceContainer: (if DI needed)
InputQuery->>InputObject: Construct InputObject with converted input and injected services
InputObject-->>InputQuery: Instance returned
InputQuery-->>User: InputObject instance
Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
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.
Hey @koriym - I've reviewed your changes - here's some feedback:
- Consider adding a
create()alias (or deprecation shim) that delegates tonewInstance()to ease migration for existing consumers instead of removing the old method outright. - Add an explicit test that constructs
InputQuerywithout passing aFileUploadFactoryto verify the default factory fallback is instantiated and works as expected. - The CSV demo and its supporting classes are quite large—consider extracting them into a separate demo or plugin repository to keep the core library focused and maintainable.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider adding a `create()` alias (or deprecation shim) that delegates to `newInstance()` to ease migration for existing consumers instead of removing the old method outright.
- Add an explicit test that constructs `InputQuery` without passing a `FileUploadFactory` to verify the default factory fallback is instantiated and works as expected.
- The CSV demo and its supporting classes are quite large—consider extracting them into a separate demo or plugin repository to keep the core library focused and maintainable.
## Individual Comments
### Comment 1
<location> `demo/ArrayDemo.php:67` </location>
<code_context>
$controller->listUsers(...$args);
-// ArrayObject example
+// ArrayObject examplepi
$method = new ReflectionMethod($controller, 'listUsersAsArrayObject');
$args = $inputQuery->getArguments($method, $query);
</code_context>
<issue_to_address>
Typo in comment: 'examplepi' should likely be 'example'.
There's an extra 'pi' at the end of the comment that should be removed to avoid confusion.
Suggested implementation:
```
// ArrayObject example
```
```
$controller->listUsersAsArrayObject(...$args);
```
</issue_to_address>
### Comment 2
<location> `demo/csv/UserInput.php:36` </location>
<code_context>
+
+ public function __toString(): string
+ {
+ $age = $this->age ? " (Age: {$this->age})" : '';
+ $dept = $this->department ? " [{$this->department}]" : '';
+
</code_context>
<issue_to_address>
Potentially misleading age display for age=0.
Since age=0 is treated as falsy, it won't be displayed. Use an explicit check (e.g., isset or $this->age !== null) to ensure zero is shown if valid.
</issue_to_address>
### Comment 3
<location> `demo/csv/CsvDemo.php:94` </location>
<code_context>
+ $method2 = new \ReflectionMethod(self::class, 'dump2');
+
+ // Step 4: Process each CSV row with Ray.InputQuery
+ foreach ($csvData as $row) {
+ // Raw CSV data transformed to associative array
+ $query = ['name' => $row[0], 'email' => $row[1], 'age' => $row[2], 'role' => $row[3]];
+
+ // Ray.InputQuery creates arguments with automatic type conversion
+ $args1 = $inputQuery->getArguments($method1,$query); // Primitive types approach
+ $args2 = $inputQuery->getArguments($method2,$query); // Input object approach
+
+ // Invoke methods with type-safe arguments
+ $method1->invokeArgs($this, $args1);
+ $method2->invokeArgs($this, $args2);
+ }
+
</code_context>
<issue_to_address>
No check for empty or malformed CSV rows.
This could cause undefined index errors if a row is empty or has fewer than four columns. Please add a check to skip such rows.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
// Step 4: Process each CSV row with Ray.InputQuery
foreach ($csvData as $row) {
// Raw CSV data transformed to associative array
$query = ['name' => $row[0], 'email' => $row[1], 'age' => $row[2], 'role' => $row[3]];
// Ray.InputQuery creates arguments with automatic type conversion
$args1 = $inputQuery->getArguments($method1,$query); // Primitive types approach
$args2 = $inputQuery->getArguments($method2,$query); // Input object approach
// Invoke methods with type-safe arguments
$method1->invokeArgs($this, $args1);
$method2->invokeArgs($this, $args2);
}
=======
// Step 4: Process each CSV row with Ray.InputQuery
foreach ($csvData as $row) {
// Skip empty or malformed rows (must have at least 4 columns)
if (!is_array($row) || count($row) < 4) {
continue;
}
// Raw CSV data transformed to associative array
$query = ['name' => $row[0], 'email' => $row[1], 'age' => $row[2], 'role' => $row[3]];
// Ray.InputQuery creates arguments with automatic type conversion
$args1 = $inputQuery->getArguments($method1,$query); // Primitive types approach
$args2 = $inputQuery->getArguments($method2,$query); // Input object approach
// Invoke methods with type-safe arguments
$method1->invokeArgs($this, $args1);
$method2->invokeArgs($this, $args2);
}
>>>>>>> REPLACE
</suggested_fix>
### Comment 4
<location> `demo/csv/CsvDemo.php:115` </location>
<code_context>
+ $ageGroup = $addGroup->getGroups();
+ $ageGroup = array_unique($ageGroup);
+ echo "Age group: " . json_encode($ageGroup) . "\n";
+ exit;
+
+ }
</code_context>
<issue_to_address>
Use of exit in library/demo code may hinder integration.
Consider returning from the function instead of calling exit, so that script termination is controlled by the caller.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
echo "Age group: " . json_encode($ageGroup) . "\n";
exit;
}
=======
echo "Age group: " . json_encode($ageGroup) . "\n";
return;
}
>>>>>>> REPLACE
</suggested_fix>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Change fileUploadFactory property type to non-nullable - Use explicit assignment instead of null coalescing assignment - Maintains optional constructor parameter while ensuring type safety 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (9)
.gitignore (1)
15-16: Redundant pattern for.DS_Storevariants
*.DS_Store?is effectively covered by the standalone.DS_Storerule because a pattern without a slash already matches in every directory. The extra line adds no benefit and marginally clutters the file.-.DS_Store?src/InputQueryInterface.php (1)
24-32: Method renamed correctly with minor documentation suggestionThe interface method has been properly renamed from
createtonewInstancewhile maintaining the same signature and functionality.Consider updating the docblock to align with the new method name:
- /** - * Create object from query data - * - * @param class-string<T> $class - * @param Query $query HTTP request data ($_POST, $_GET, etc.) - * - * @return T - */ + /** + * Create new instance from query data + * + * @param class-string<T> $class + * @param Query $query HTTP request data ($_POST, $_GET, etc.) + * + * @return T + */demo/csv/run.php (4)
11-12: Remove extra blank line.- - +
16-19: Remove unused imports.The following classes are imported but not used in this file:
CsvFileInputCsvToInputConverterCsvUsersImportuse Ray\InputQuery\Demo\CsvDemo; -use Ray\InputQuery\Demo\CsvFileInput; -use Ray\InputQuery\Demo\CsvToInputConverter; -use Ray\InputQuery\Demo\CsvUsersImport; use Ray\InputQuery\InputQuery;
22-24: Simplify array parameter formatting.-$csvFile = FileUpload::fromFile(__DIR__ . '/users.csv',[ -]); +$csvFile = FileUpload::fromFile(__DIR__ . '/users.csv', []);
39-39: Add newline at end of file.echo "🔹 Clean separation of concerns\n"; +demo/csv/UserInput.php (1)
30-31: Translate Japanese comment to English for consistency.- // 年齢グループに自動登録 + // Automatically register with age group $this->ageGroup?->addAge($this->age);demo/csv/CsvDemo.php (2)
99-100: Fix formatting: add space after comma in method calls.- $args1 = $inputQuery->getArguments($method1,$query); // Primitive types approach - $args2 = $inputQuery->getArguments($method2,$query); // Input object approach + $args1 = $inputQuery->getArguments($method1, $query); // Primitive types approach + $args2 = $inputQuery->getArguments($method2, $query); // Input object approach
139-139: Clarify age property access pattern.The mixed access to age properties (
$user->agevs$user->ageInput->age) is confusing and suggests unclear data structure.- echo "dump2: Name: $user->name Email: $user->email Age: {$user->ageInput->age}:{$user->age}\n"; + echo "dump2: Name: $user->name Email: $user->email Age: {$user->age} (validated: {$user->ageInput->age})\n";This makes it clearer that there are two age representations - the raw age and the validated age from the AgeInput object.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
demo/csv/tmp/saved.csvis excluded by!**/*.csvdemo/csv/users.csvis excluded by!**/*.csv
📒 Files selected for processing (18)
.gitignore(1 hunks)README.md(8 hunks)demo/ArrayDemo.php(2 hunks)demo/csv/AgeGroup.php(1 hunks)demo/csv/AgeInput.php(1 hunks)demo/csv/CsvDemo.php(1 hunks)demo/csv/UserInput.php(1 hunks)demo/csv/run.php(1 hunks)demo/run.php(8 hunks)docs/design/design.md(2 hunks)docs/design/file-upload-integration.md(3 hunks)docs/framework_integration.md(1 hunks)docs/prompts/usage-generator.md(3 hunks)src/InputQuery.php(4 hunks)src/InputQueryInterface.php(1 hunks)tests/FileUploadTest.php(4 hunks)tests/InputFileTest.php(11 hunks)tests/InputQueryTest.php(22 hunks)
🧰 Additional context used
🧠 Learnings (14)
📓 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/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
src/InputQueryInterface.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/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/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 : 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 : For parameters without #[Input], resolve them from the DI container, supporting #[Named] for scalar DI values.
demo/ArrayDemo.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/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
docs/prompts/usage-generator.md (8)
Learnt from: CR
PR: ray-di/Ray.InputQuery#0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:18:36.698Z
Learning: Only depend on `ray/di` for `InjectorInterface`.
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 : 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/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/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 : 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/**/*.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 : Implement a reasonable recursion depth limit (e.g., 10 levels) to prevent infinite recursion in nested input resolution.
tests/InputFileTest.php (8)
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.
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/**/*.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.
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 : 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 : For parameters with #[Input] and object type, extract prefixed keys from flat query and recursively create nested objects.
docs/framework_integration.md (6)
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/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/**/*.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 with #[Input] but missing from query: use parameter default or null if allowed.
tests/FileUploadTest.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/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
demo/run.php (5)
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/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 : 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 : Convert all query keys to camelCase, handling snake_case, kebab-case, and PascalCase.
tests/InputQueryTest.php (9)
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/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 : 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 : 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 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/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/**/*.php : The #[Input] attribute must be applied to parameters, not classes.
docs/design/design.md (5)
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/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 : 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 : 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.
demo/csv/AgeInput.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 : 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/**/*.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/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/InputQuery.php : Parameters without #[Input] that can't be resolved by DI: use parameter default or throw exception.
src/InputQuery.php (5)
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/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 : 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.
demo/csv/UserInput.php (8)
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/**/*.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.
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 : 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 : 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 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/InputQueryInterface.php : InputQueryInterface must define getArguments(ReflectionMethod $method, array $query): array and create(string $class, array $query): object.
README.md (11)
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/**/*.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 : 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 : 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/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/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/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/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/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: Only depend on `ray/di` for `InjectorInterface`.
🧬 Code Graph Analysis (2)
tests/FileUploadTest.php (5)
src/InputQueryInterface.php (1)
newInstance(32-32)tests/Fake/FileUploadInput.php (1)
FileUploadInput(11-18)tests/Fake/FileUploadWithOptionsInput.php (1)
FileUploadWithOptionsInput(11-18)tests/Fake/OptionalFileUploadInput.php (1)
OptionalFileUploadInput(12-19)tests/Fake/FileUploadArrayInput.php (1)
FileUploadArrayInput(10-20)
demo/csv/AgeGroup.php (1)
src/InputQuery.php (1)
InputQuery(70-504)
🪛 PHPMD (2.15.0)
demo/csv/CsvDemo.php
68-68: Avoid unused parameters such as '$hasHeader'. (Unused Code Rules)
(UnusedFormalParameter)
69-69: Avoid unused parameters such as '$encoding'. (Unused Code Rules)
(UnusedFormalParameter)
70-70: Avoid unused parameters such as '$skipEmptyRows'. (Unused Code Rules)
(UnusedFormalParameter)
133-133: Avoid unused parameters such as '$email'. (Unused Code Rules)
(UnusedFormalParameter)
🔇 Additional comments (17)
.gitignore (1)
9-12: Uploaded-file directories correctly excluded
Addingdemo/uploads/anduploads/keeps transient artefacts out of the repo—good call.demo/csv/AgeGroup.php (1)
1-54: Excellent implementation of a stateful service.This class demonstrates solid design principles:
- Clear separation of concerns with business logic isolated from input handling
- Proper null safety handling
- Well-defined age group boundaries without gaps or overlaps
- Comprehensive documentation explaining the singleton service pattern
- Clean, readable implementation
The age grouping logic correctly handles all ranges: <25, 25-35, 36-50, >50.
docs/prompts/usage-generator.md (1)
41-41: LGTM: Consistent method renaming implementation.All occurrences of
create()have been properly updated tonewInstance(), maintaining the same API usage patterns while aligning with the new naming convention. The changes are applied consistently across both basic usage and multi-step form examples.Also applies to: 215-215, 218-218
docs/framework_integration.md (1)
554-554: LGTM: Documentation updated for new method name.The change correctly updates the direct object creation pattern example to use
newInstance()instead ofcreate(), maintaining consistency with the API renaming throughout the codebase.docs/design/file-upload-integration.md (2)
175-175: LGTM: Testing examples updated for new API.The file upload testing examples have been correctly updated to use
newInstance()instead ofcreate(), maintaining the same functionality and testing patterns while aligning with the new method naming convention.Also applies to: 314-314
363-363: Good practice: Added newline at EOF.Adding a newline character at the end of the file follows standard file formatting conventions.
tests/FileUploadTest.php (1)
43-43: LGTM: Method calls updated consistentlyThe file upload tests have been correctly updated to use the new
newInstance()method name instead ofcreate(). All test logic and assertions remain unchanged, maintaining the same test coverage and behavior.Also applies to: 67-67, 81-81, 110-110
tests/InputFileTest.php (1)
41-41: Comprehensive method renaming completed correctlyAll test methods in the file input test suite have been consistently updated to use
newInstance()instead ofcreate(). The changes preserve all test logic and maintain comprehensive coverage of file input scenarios including validation, error handling, and edge cases.Also applies to: 58-58, 76-76, 97-97, 117-117, 137-137, 157-157, 177-177, 196-196, 210-210, 219-219, 1048-1048, 1118-1118, 1136-1136
docs/design/design.md (1)
343-343: Documentation examples updated to reflect new APIThe design documentation has been correctly updated to demonstrate usage of the new
newInstance()method instead ofcreate(). This ensures developers have accurate examples of the current API.Also applies to: 374-374
tests/InputQueryTest.php (1)
96-96: Extensive test suite updated consistently and thoroughlyThe main test suite has been comprehensively updated with all
create()method calls replaced bynewInstance(). This covers the full range of functionality including:
- Simple and nested object creation
- DI integration and mixed parameters
- Scalar type conversions and validation
- File upload handling
- Error scenarios and edge cases
- Array processing and complex types
All test logic and assertions are preserved, ensuring continued comprehensive test coverage with the new API.
Also applies to: 111-111, 128-128, 165-165, 184-184, 202-202, 230-230, 240-240, 259-259, 273-273, 289-289, 301-301, 317-317, 335-335, 372-372, 384-384, 415-415, 431-431, 448-448, 1048-1048, 1118-1118, 1136-1136
demo/csv/AgeInput.php (1)
1-29: Well-designed value object with proper domain validation.The implementation correctly enforces the "creation = validity" principle, ensuring that invalid
AgeInputinstances cannot exist. The use of readonly properties and comprehensive documentation makes this a good example of input object design.demo/run.php (1)
33-33: Changes correctly implement the API updates.All modifications align with the PR objectives:
- Constructor simplification reflects the optional
FileUploadFactorydependency- Method calls properly updated from
create()tonewInstance()- Minor whitespace cleanup improves code quality
Also applies to: 47-47, 64-64, 96-96, 110-110, 126-126, 145-145, 168-168
src/InputQuery.php (1)
74-77: Excellent implementation of the API improvements.The changes successfully achieve the PR objectives:
- Optional
FileUploadFactorywith automatic default instantiation simplifies usage while preserving DI flexibility- Method rename to
newInstance()provides clearer semantics- All internal calls properly updated for consistency
Also applies to: 101-101, 275-275, 481-481
README.md (4)
27-27: Good fix: Added missing code block delimiter.This resolves the syntax error in the markdown formatting.
103-103: Excellent consistency: Method name changes properly implemented.All instances of
create()have been correctly updated tonewInstance()throughout the documentation, maintaining consistency with the API changes.Also applies to: 144-144, 356-356, 423-423, 435-435, 483-483, 492-492
126-154: Improved example: Better nested object demonstration.The updated nested objects example using
AddressInputandUserInputis more practical and easier to understand than the previous example.
303-369: Excellent addition: Comprehensive dependency injection example.The new
EventBookingInputexample demonstrates advanced concepts beautifully:
- Interface-based dependency injection
- Named parameter binding
- Complex object creation with validation
- Exception handling for business logic
- Real-world use case with tickets and addresses
This significantly improves the documentation quality and demonstrates the power of combining Ray.InputQuery with dependency injection.
- Add NullUploadFactory as default when FileUploadFactory not provided - Change return type to AbstractFileUpload for better type safety - Update tests to use FileUploadFactory only when needed - Update demos to explicitly use FileUploadFactory for file uploads - Update README to document optional koriym/file-upload dependency - Address code review feedback: fix typos, fix age=0 display, replace exit with return BREAKING CHANGE: FileUploadFactory must be explicitly provided when using file upload features 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- InputQueryTest contains file upload test methods that require FileUploadFactory - Changed setUp() to use FileUploadFactory instead of default NullUploadFactory - This allows file upload tests to work while keeping core functionality separate 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
AbstractFileUpload is used in FileUploadFactoryInterface return types but is an optional dependency. Adding it to the whitelist allows the optional file upload functionality to work correctly. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Summary
create()tonewInstance()for clearer method naming and better API consistencyAPI Changes
Before
After
DI Improvements
Documentation Enhancements
Test Plan
🤖 Generated with Claude Code
Summary by Sourcery
Replace the legacy create() method with newInstance(), make the FileUploadFactory optional by providing a default instance, update all code samples and tests to reflect the new API, and enrich the documentation with expanded DI examples and a comprehensive CSV import demo.
New Features:
Enhancements:
Documentation:
Tests:
Summary by CodeRabbit
New Features
Documentation
newInstance()instead ofcreate()for input object instantiation.Bug Fixes
.gitignoreto exclude common OS and upload-related files from version control.Refactor
create()tonewInstance()throughout the codebase and tests.Tests
newInstance()method for input creation.