@@ -43,8 +43,9 @@ of them to type-safe objects.
4343 - [All fields are required](#all-fields-are-required)
4444 - [No fields are required](#no-fields-are-required)
4545- [ Callbacks] ( #callbacks )
46- - [Mapped object callbacks](#mapped-object-callbacks)
47- - [Field callbacks](#field-callbacks)
46+ - [Validation object callbacks](#validation-object-callbacks)
47+ - [After mapping object callbacks](#after-mapping-object-callbacks)
48+ - [Validation field callbacks](#validation-field-callbacks)
4849 - [Returned value](#returned-value)
4950 - [Context](#callback-context)
5051- [ Dependencies] ( #dependencies )
@@ -1223,7 +1224,7 @@ use Orisai\ObjectMapper\Rules\MixedValue;
12231224final class ListOfInput implements MappedObject
12241225{
12251226
1226- /** @var list<int , mixed > */
1227+ /** @var list<mixed > */
12271228 #[ListOf(new MixedValue())]
12281229 public array $field;
12291230
@@ -1253,7 +1254,7 @@ final class ListOfInput implements MappedObject
12531254{
12541255
12551256 /**
1256- * @var list<int , mixed >
1257+ * @var list<mixed >
12571258 * @ListOf(
12581259 * @MixedValue(),
12591260 * )
@@ -2224,13 +2225,13 @@ final class WithCallbackInput implements MappedObject
22242225callbacks are called and overwrites any of set values.
22252226
22262227In all callbacks are used [ field names] ( #mapping-field-names-to-properties ) , not property names.
2227- In [ field callbacks] ( #field-callbacks ) , current field name can be accessed via [ context] ( #callback-context ) .
2228+ In [ field callbacks] ( #validation- field-callbacks ) , current field name can be accessed via [ context] ( #callback-context ) .
22282229
22292230Callbacks can be both static and non-static, object mapper initializes object to call non-static callbacks when needed.
22302231
22312232Callbacks can have any visibility - public, protected or private.
22322233
2233- ### Mapped object callbacks
2234+ ### Validation object callbacks
22342235
22352236Modify and check data before and after processing fields with their rules
22362237
@@ -2319,7 +2320,83 @@ final class WithMappedObjectCallbacksInput implements MappedObject
23192320```
23202321</details >
23212322
2322- ### Field callbacks
2323+ ### After mapping object callbacks
2324+
2325+ Validate object after being fully initialized
2326+
2327+ <details open >
2328+ <summary><code>#[Attributes()]</code></summary>
2329+
2330+ ``` php
2331+ use Orisai\ObjectMapper\Callbacks\AfterMapping;
2332+ use Orisai\ObjectMapper\Callbacks\Context\ObjectContext;
2333+ use Orisai\ObjectMapper\MappedObject;
2334+ use Orisai\ObjectMapper\Rules\ListOf;
2335+ use Orisai\ObjectMapper\Rules\StringValue;
2336+
2337+ #[AfterMapping('afterObject')]
2338+ final class AfterMappingCallbackInput implements MappedObject
2339+ {
2340+
2341+ /** @var list<string > */
2342+ #[ListOf(new StringValue())]
2343+ public array $allowed = [];
2344+
2345+ /** @var list<string > */
2346+ #[ListOf(new StringValue())]
2347+ public array $forbidden = [];
2348+
2349+ private function afterObject(ObjectContext $context): void
2350+ {
2351+ if ($this->allowed !== [] && $this->forbidden !== []) {
2352+ $context->getType()->addError("Specify either 'allowed' or 'forbidden', not both.");
2353+ }
2354+ }
2355+
2356+ }
2357+ ```
2358+ </details >
2359+
2360+ <details >
2361+ <summary><code>@Annotations()</code></summary>
2362+
2363+ ``` php
2364+ use Orisai\ObjectMapper\Callbacks\AfterMapping;
2365+ use Orisai\ObjectMapper\Callbacks\Context\ObjectContext;
2366+ use Orisai\ObjectMapper\MappedObject;
2367+ use Orisai\ObjectMapper\Rules\ListOf;
2368+ use Orisai\ObjectMapper\Rules\StringValue;
2369+
2370+ /**
2371+ * @AfterMapping("afterObject")
2372+ */
2373+ final class AfterMappingCallbackInput implements MappedObject
2374+ {
2375+
2376+ /**
2377+ * @var list<string >
2378+ * @ListOf(@StringValue())
2379+ */
2380+ public array $allowed = [];
2381+
2382+ /**
2383+ * @var list<string >
2384+ * @ListOf(@StringValue())
2385+ */
2386+ public array $forbidden = [];
2387+
2388+ private function afterObject(ObjectContext $context): void
2389+ {
2390+ if ($this->allowed !== [] && $this->forbidden !== []) {
2391+ $context->getType()->addError("Specify either 'allowed' or 'forbidden', not both.");
2392+ }
2393+ }
2394+
2395+ }
2396+ ```
2397+ </details >
2398+
2399+ ### Validation field callbacks
23232400
23242401Modify and check data before and after processing field with its rule
23252402
@@ -2441,7 +2518,8 @@ $input = $processor->process(['field' => 'new value'], WithNotInvokedCallbackInp
24412518
24422519### Returned value
24432520
2444- Callbacks are by default expected to return a value:
2521+ [ Validation object callbacks] ( #validation-object-callbacks ) and
2522+ [ validation field callbacks] ( #validation-field-callbacks ) are by default expected to return a value:
24452523
24462524<details open >
24472525 <summary><code>#[Attributes()]</code></summary>
@@ -2556,23 +2634,21 @@ final class WithNotReturningCallbackInput implements MappedObject
25562634
25572635### Callback context
25582636
2559- Both [ mapped object callbacks] ( #mapped -object-callbacks ) and [ field callbacks] ( #field-callbacks ) have additional context
2637+ [ Validation object callbacks] ( #validation -object-callbacks ) and [ validation field callbacks] ( #validation- field-callbacks ) have additional context
25602638available as a second parameter, for extended processing:
25612639
25622640Mapped object and field contexts
25632641
25642642``` php
25652643$context->getProcessor(); // Processor
25662644$context->getOptions(); // Options
2567- $context->shouldMapDataToObjects (); // bool
2645+ $context->shouldInitializeObjects (); // bool
25682646$context->getType(); // Type
25692647```
25702648
25712649Field context
25722650
25732651``` php
2574- $context->hasDefaultValue(); // bool
2575- $context->getDefaultValue(); // mixed|exception
25762652$context->getFieldName(); // int|string
25772653$context->getPropertyName(); // string
25782654```
0 commit comments