|
| 1 | +# ObjectConstructorSchema |
| 2 | + |
| 3 | +The `ObjectConstructorSchema` parses an associative array (or compatible input) and constructs an instance of a given class by passing validated fields to its constructor. |
| 4 | + |
| 5 | +## Basic Usage |
| 6 | + |
| 7 | +```php |
| 8 | +<?php |
| 9 | + |
| 10 | +use Chubbyphp\Parsing\Parser; |
| 11 | + |
| 12 | +class User |
| 13 | +{ |
| 14 | + public function __construct( |
| 15 | + public readonly string $name, |
| 16 | + public readonly int $age |
| 17 | + ) {} |
| 18 | +} |
| 19 | + |
| 20 | +$p = new Parser(); |
| 21 | + |
| 22 | +$schema = $p->objectConstructor([ |
| 23 | + 'name' => $p->string(), |
| 24 | + 'age' => $p->int(), |
| 25 | +], User::class); |
| 26 | + |
| 27 | +$user = $schema->parse(['name' => 'John', 'age' => 30]); |
| 28 | +// Returns: User instance with populated properties |
| 29 | +``` |
| 30 | + |
| 31 | +## Constructor Validation |
| 32 | + |
| 33 | +The schema validates that: |
| 34 | +1. All non-optional constructor parameters have a corresponding schema definition. |
| 35 | +2. No extra schemas are provided that don't match a constructor parameter. |
| 36 | +3. The types of the parsed values match the constructor parameter types (handling `TypeError` automatically). |
| 37 | + |
| 38 | +## Supported Input Types |
| 39 | + |
| 40 | +The `ObjectConstructorSchema` accepts multiple input formats, which are converted to an associative array before processing: |
| 41 | + |
| 42 | +- **Arrays** - Standard associative arrays |
| 43 | +- **stdClass** - Anonymous objects |
| 44 | +- **Traversable** - Objects implementing `\Traversable` |
| 45 | +- **JsonSerializable** - Objects implementing `\JsonSerializable` |
| 46 | + |
| 47 | +## Validations |
| 48 | + |
| 49 | +### Strict Mode |
| 50 | + |
| 51 | +By default, unknown fields in the input are silently ignored. Use `strict()` to reject unknown fields: |
| 52 | + |
| 53 | +```php |
| 54 | +$schema = $p->objectConstructor([ |
| 55 | + 'name' => $p->string() |
| 56 | +], User::class)->strict(); |
| 57 | + |
| 58 | +$schema->parse(['name' => 'John']); // OK |
| 59 | +$schema->parse(['name' => 'John', 'extra' => 1]); // Throws error: object.unknownField |
| 60 | +``` |
| 61 | + |
| 62 | +### Strict with Exceptions |
| 63 | + |
| 64 | +Allow specific unknown fields to be ignored while rejecting others: |
| 65 | + |
| 66 | +```php |
| 67 | +$schema = $p->objectConstructor([ |
| 68 | + 'name' => $p->string() |
| 69 | +], User::class)->strict(['_id', '_rev']); |
| 70 | + |
| 71 | +$schema->parse(['name' => 'John', '_id' => '123']); // OK, _id ignored |
| 72 | +$schema->parse(['name' => 'John', 'unknown' => 'val']); // Throws error: object.unknownField |
| 73 | +``` |
| 74 | + |
| 75 | +### Optional Fields |
| 76 | + |
| 77 | +Make certain fields optional in the input. If an optional field is missing from the input, it won't be passed to the constructor (so the constructor parameter must be optional). |
| 78 | + |
| 79 | +```php |
| 80 | +class User |
| 81 | +{ |
| 82 | + public function __construct( |
| 83 | + public readonly string $name, |
| 84 | + public readonly string $nickname = '' |
| 85 | + ) {} |
| 86 | +} |
| 87 | + |
| 88 | +$schema = $p->objectConstructor([ |
| 89 | + 'name' => $p->string(), |
| 90 | + 'nickname' => $p->string(), |
| 91 | +], User::class)->optional(['nickname']); |
| 92 | + |
| 93 | +$schema->parse(['name' => 'John']); |
| 94 | +// Returns: User(name: 'John', nickname: '') - using default value from constructor |
| 95 | +``` |
| 96 | + |
| 97 | +## Schema Utilities |
| 98 | + |
| 99 | +### Get Field Schema |
| 100 | + |
| 101 | +Retrieve the schema for a specific field: |
| 102 | + |
| 103 | +```php |
| 104 | +$nameSchema = $schema->getFieldSchema('name'); // Returns StringSchema |
| 105 | +``` |
| 106 | + |
| 107 | +### Extend Schema |
| 108 | + |
| 109 | +Get all field schemas to extend or compose: |
| 110 | + |
| 111 | +```php |
| 112 | +$baseSchema = $p->objectConstructor([ |
| 113 | + 'id' => $p->int(), |
| 114 | +], BaseEntity::class); |
| 115 | + |
| 116 | +$userSchema = $p->objectConstructor([ |
| 117 | + ...$baseSchema->getFieldToSchema(), |
| 118 | + 'name' => $p->string(), |
| 119 | +], User::class); |
| 120 | +``` |
| 121 | + |
| 122 | +## Error Codes |
| 123 | + |
| 124 | +| Code | Description | |
| 125 | +|------|-------------| |
| 126 | +| `object.type` | Value is not a valid object type (array, stdClass, Traversable) | |
| 127 | +| `object.unknownField` | Unknown field found in strict mode | |
| 128 | +| `object.parameterType` | Constructor parameter type mismatch (e.g., int passed to string parameter) | |
| 129 | + |
| 130 | +Field-level errors (like validation failures within `name` or `age` schemas) include the field name in the error path. |
0 commit comments