9292/**
9393 * @property int $quantity PHPDoc defined dynamic properties will be validated on every set
9494 */
95- class Example extends ClassStructure
95+ class User extends ClassStructure
9696{
9797 /* Native (public) properties will be validated only on import and export of structure data */
9898
@@ -102,30 +102,53 @@ class Example extends ClassStructure
102102 /** @var Order[] */
103103 public $orders;
104104
105+ /** @var UserInfo */
106+ public $info;
107+
105108 /**
106- * Define your properties
107- *
108109 * @param Properties|static $properties
109110 * @param Schema $ownerSchema
110111 */
111112 public static function setUpProperties($properties, Schema $ownerSchema)
112113 {
114+ // Setup property schemas
113115 $properties->id = Schema::integer();
114116 $properties->name = Schema::string();
115117
118+ // You can embed structures to main level with nested schemas
119+ $properties->info = UserInfo::schema()->nested();
120+
121+ // Dynamic (phpdoc-defined) properties can be used as well
116122 $properties->quantity = Schema::integer();
117123 $properties->quantity->minimum = 0;
118124
125+ // Property can be any complex structure
119126 $properties->orders = Schema::create();
120127 $properties->orders->items = Order::schema();
121128
122129 $ownerSchema->required = array(self::names()->id);
123130 }
124131}
125132
126- /**
127- *
128- */
133+
134+ class UserInfo extends ClassStructure {
135+ public $firstName;
136+ public $lastName;
137+ public $birthDay;
138+
139+ /**
140+ * @param Properties|static $properties
141+ * @param Schema $ownerSchema
142+ */
143+ public static function setUpProperties($properties, Schema $ownerSchema)
144+ {
145+ $properties->firstName = Schema::string();
146+ $properties->lastName = Schema::string();
147+ $properties->birthDay = Schema::string();
148+ }
149+ }
150+
151+
129152class Order extends ClassStructure
130153{
131154 public $id;
@@ -139,7 +162,7 @@ class Order extends ClassStructure
139162 public static function setUpProperties($properties, Schema $ownerSchema)
140163 {
141164 $properties->id = Schema::integer();
142- $properties->dateTime = Schema::string();
165+ $properties->dateTime = Schema::string()->meta(new FieldName('date_time')) ;
143166 $properties->dateTime->format = Schema::FORMAT_DATE_TIME;
144167 $properties->price = Schema::number();
145168
@@ -152,26 +175,134 @@ Validation of dynamic properties is performed on set,
152175this can help to find source of invalid data at cost of
153176some performance drop
154177``` php
155- $example = new Example ();
156- $example ->quantity = -1; // Exception: Value more than 0 expected, -1 received
178+ $user = new User ();
179+ $user ->quantity = -1; // Exception: Value more than 0 expected, -1 received
157180```
158181
159182Validation of native properties is performed only on import/export
160183``` php
161- $example = new Example ();
162- $example ->quantity = 10;
163- Example ::export($example ); // Exception: Required property missing: id
184+ $user = new User ();
185+ $user ->quantity = 10;
186+ User ::export($user ); // Exception: Required property missing: id
164187```
165188
166189Error messages provide a path to invalid data
167190``` php
168- $example = new Example ();
169- $example ->id = 1;
170- $example ->name = 'John Doe';
191+ $user = new User ();
192+ $user ->id = 1;
193+ $user ->name = 'John Doe';
171194
172195$order = new Order();
173196$order->dateTime = (new \DateTime())->format(DATE_RFC3339);
174- $example ->orders[] = $order;
197+ $user ->orders[] = $order;
175198
176- Example::export($example); // Exception: Required property missing: id at #->properties:orders->items[0]
199+ User::export($user); // Exception: Required property missing: id at #->properties:orders->items[0]
200+ ```
201+
202+ #### Nested structures
203+
204+ Nested structures allow you to make composition: flatten several objects in one and separate back.
205+
206+ ``` php
207+ $user = new User();
208+ $user->id = 1;
209+
210+ $info = new UserInfo();
211+ $info->firstName = 'John';
212+ $info->lastName = 'Doe';
213+ $info->birthDay = '1970-01-01';
214+ $user->info = $info;
215+
216+ $json = <<<JSON
217+ {
218+ " id" : 1,
219+ " firstName" : " John" ,
220+ " lastName" : " Doe" ,
221+ " birthDay" : " 1970-01-01"
222+ }
223+ JSON;
224+ $exported = User::export($user);
225+ $this- >assertSame($json, json_encode($exported, JSON_PRETTY_PRINT));
226+
227+ $imported = User::import(json_decode($json));
228+ $this->assertSame('John', $imported->info->firstName);
229+ $this->assertSame('Doe', $imported->info->lastName);
230+ ```
231+
232+ You can also use ` \Swaggest\JsonSchema\Structure\Composition ` to dynamically create schema compositions.
233+ This can be helpful to deal with results of database query on joined data.
234+
235+ ``` php
236+ $schema = new Composition(UserInfo::schema(), Order::schema());
237+ $json = <<<JSON
238+ {
239+ " id" : 1,
240+ " firstName" : " John" ,
241+ " lastName" : " Doe" ,
242+ " price" : 2.66
243+ }
244+ JSON;
245+ $object = $schema- >import(json_decode($json));
246+
247+ // Get particular object with `pick` accessor
248+ $info = UserInfo::pick($object);
249+ $order = Order::pick($object);
250+
251+ // Data is imported objects of according classes
252+ $this->assertTrue($order instanceof Order);
253+ $this->assertTrue($info instanceof UserInfo);
254+
255+ $this->assertSame(1, $order->id);
256+ $this->assertSame('John', $info->firstName);
257+ $this->assertSame('Doe', $info->lastName);
258+ $this->assertSame(2.66, $order->price);
259+ ```
260+
261+ #### Keys mapping
262+
263+ If property names of PHP objects should be different from raw data you
264+ can apply ` \Swaggest\JsonSchema\PreProcessor\NameMapper ` during processing.
265+ It takes ` Swaggest\JsonSchema\Meta\FieldName ` as source of raw name.
266+
267+ ``` php
268+ $properties->dateTime = Schema::string()->meta(new FieldName('date_time'));
269+ ```
270+
271+ ``` php
272+ $mapper = new NameMapper();
273+
274+ $order = new Order();
275+ $order->id = 1;
276+ $order->dateTime = '2015-10-28T07:28:00Z';
277+ $exported = Order::export($order, $mapper);
278+ $json = <<<JSON
279+ {
280+ " id" : 1,
281+ " date_time" : " 2015-10-28T07:28:00Z"
282+ }
283+ JSON;
284+ $this- >assertSame($json, json_encode($exported, JSON_PRETTY_PRINT));
285+
286+ $imported = Order::import(json_decode($json), $mapper);
287+ $this->assertSame('2015-10-28T07:28:00Z', $imported->dateTime);
288+ ```
289+
290+ You can create your own pre-processor implementing ` Swaggest\JsonSchema\DataPreProcessor ` .
291+
292+ #### Meta
293+
294+ ` Meta ` is a way to complement ` Schema ` with your own data. You can keep and retrieve it.
295+
296+ You can store it.
297+ ``` php
298+ $schema = new Schema();
299+ // Setting meta
300+ $schema->meta(new FieldName('my-value'));
301+ ```
302+
303+ And get back.
304+ ``` php
305+ // Retrieving meta
306+ $myMeta = FieldName::get($schema);
307+ $this->assertSame('my-value', $myMeta->name);
177308```
0 commit comments