diff --git a/docs/docs.json b/docs/docs.json
index c124427..1007b9e 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -59,14 +59,6 @@
"json-schema/code-generation/from-enums",
"json-schema/code-generation/from-json"
]
- },
- {
- "group": "Validation",
- "pages": [
- "json-schema/validation/data-validation",
- "json-schema/validation/error-handling",
- "json-schema/validation/version-features"
- ]
}
]
}
diff --git a/docs/json-schema/advanced/conditional-validation.mdx b/docs/json-schema/advanced/conditional-validation.mdx
index 004cd17..79bfbff 100644
--- a/docs/json-schema/advanced/conditional-validation.mdx
+++ b/docs/json-schema/advanced/conditional-validation.mdx
@@ -628,22 +628,3 @@ $complexSchema = Schema::object('complex_validation')
Different validation rules for different API versions or client types.
-
-## Next Steps
-
-
-
- Learn to create reusable schema components for complex conditional logic
-
-
- Explore property-dependent validation in modern JSON Schema versions
-
-
diff --git a/docs/json-schema/advanced/definitions-refs.mdx b/docs/json-schema/advanced/definitions-refs.mdx
index 38ca420..50c9e49 100644
--- a/docs/json-schema/advanced/definitions-refs.mdx
+++ b/docs/json-schema/advanced/definitions-refs.mdx
@@ -539,22 +539,3 @@ $schema->addDefinition(
Reuse field validation patterns across different forms and input structures.
-
-## Next Steps
-
-
-
- Learn how to use definitions with conditional validation logic
-
-
- Generate schemas with definitions from PHP classes
-
-
diff --git a/docs/json-schema/advanced/dependent-schemas.mdx b/docs/json-schema/advanced/dependent-schemas.mdx
index 43abe3f..70ae0c4 100644
--- a/docs/json-schema/advanced/dependent-schemas.mdx
+++ b/docs/json-schema/advanced/dependent-schemas.mdx
@@ -563,22 +563,3 @@ $schema->dependentSchemas([
Profile settings where enabled features require additional information.
-
-## Next Steps
-
-
-
- Learn about regex-based property validation patterns
-
-
- Master if/then/else and other conditional validation techniques
-
-
diff --git a/docs/json-schema/advanced/pattern-properties.mdx b/docs/json-schema/advanced/pattern-properties.mdx
index 5c71f0c..25a8a86 100644
--- a/docs/json-schema/advanced/pattern-properties.mdx
+++ b/docs/json-schema/advanced/pattern-properties.mdx
@@ -489,22 +489,3 @@ $schema->patternProperties([
Allow users to define custom fields that follow specific naming rules.
-
-## Next Steps
-
-
-
- Learn more about object validation and additional properties
-
-
- Generate schemas with pattern properties from PHP classes
-
-
diff --git a/docs/json-schema/advanced/string-formats.mdx b/docs/json-schema/advanced/string-formats.mdx
index e6b4ae4..3a23a71 100644
--- a/docs/json-schema/advanced/string-formats.mdx
+++ b/docs/json-schema/advanced/string-formats.mdx
@@ -211,22 +211,3 @@ $userProfileSchema->isValid($validProfile); // true
Validate formatted data during import processes with appropriate type checking.
-
-## Next Steps
-
-
-
- Learn more about string validation and pattern matching
-
-
- Master data validation techniques and error handling
-
-
diff --git a/docs/json-schema/advanced/unevaluated-properties.mdx b/docs/json-schema/advanced/unevaluated-properties.mdx
index cff31ad..6c5720f 100644
--- a/docs/json-schema/advanced/unevaluated-properties.mdx
+++ b/docs/json-schema/advanced/unevaluated-properties.mdx
@@ -423,22 +423,3 @@ $schema = Schema::object('strict_user', SchemaVersion::Draft_2019_09)
Validate data during migration with strict control over allowed properties and transformations.
-
-## Next Steps
-
-
-
- Learn about property-dependent validation in modern JSON Schema
-
-
- Understand JSON Schema version compatibility and feature support
-
-
diff --git a/docs/json-schema/code-generation/from-classes.mdx b/docs/json-schema/code-generation/from-classes.mdx
index dd92a73..9110b86 100644
--- a/docs/json-schema/code-generation/from-classes.mdx
+++ b/docs/json-schema/code-generation/from-classes.mdx
@@ -512,22 +512,3 @@ Validation rules like minLength, pattern, format are not extracted from docblock
Generate schemas for application configuration classes.
-
-## Next Steps
-
-
-
- Learn to generate schemas from function signatures
-
-
- Generate validation schemas from PHP enums
-
-
diff --git a/docs/json-schema/code-generation/from-closures.mdx b/docs/json-schema/code-generation/from-closures.mdx
index 3614e05..f2f3803 100644
--- a/docs/json-schema/code-generation/from-closures.mdx
+++ b/docs/json-schema/code-generation/from-closures.mdx
@@ -473,22 +473,3 @@ function handleUserStuff($data, $action, $options = []) {}
Generate validation for configuration and setup functions.
-
-## Next Steps
-
-
-
- Generate validation schemas from PHP enums
-
-
- Import and work with existing JSON Schema definitions
-
-
diff --git a/docs/json-schema/code-generation/from-enums.mdx b/docs/json-schema/code-generation/from-enums.mdx
index 2c22a8a..b847f2f 100644
--- a/docs/json-schema/code-generation/from-enums.mdx
+++ b/docs/json-schema/code-generation/from-enums.mdx
@@ -635,22 +635,3 @@ try {
Generate client-side validation and form options from backend enums.
-
-## Next Steps
-
-
-
- Import and work with existing JSON Schema definitions
-
-
- Learn advanced validation techniques for enum values
-
-
diff --git a/docs/json-schema/code-generation/from-json.mdx b/docs/json-schema/code-generation/from-json.mdx
index 977e3f0..51996ad 100644
--- a/docs/json-schema/code-generation/from-json.mdx
+++ b/docs/json-schema/code-generation/from-json.mdx
@@ -237,123 +237,6 @@ $singleUserResponse = [
$apiSchema->isValid($singleUserResponse); // true
```
-## Loading from Files
-
-Load schemas from external files:
-
-```php
-/**
- * Load schema from file
- */
-function loadSchemaFromFile(string $filepath): Schema
-{
- if (!file_exists($filepath)) {
- throw new InvalidArgumentException("Schema file not found: {$filepath}");
- }
-
- $content = file_get_contents($filepath);
- $schemaData = json_decode($content, true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new InvalidArgumentException("Invalid JSON in schema file: " . json_last_error_msg());
- }
-
- return Schema::fromJson($schemaData);
-}
-
-// Usage
-$userSchema = loadSchemaFromFile('schemas/user.json');
-$productSchema = loadSchemaFromFile('schemas/product.json');
-$orderSchema = loadSchemaFromFile('schemas/order.json');
-```
-
-## Best Practices
-
-### 1. Validate JSON Before Import
-
-```php
-function safeJsonImport(string $jsonString): Schema
-{
- $data = json_decode($jsonString, true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new InvalidArgumentException(
- "Invalid JSON: " . json_last_error_msg()
- );
- }
-
- // Basic schema validation
- if (!isset($data['type'])) {
- throw new InvalidArgumentException("Schema must have a 'type' property");
- }
-
- return Schema::fromJson($data);
-}
-```
-
-### 2. Handle Schema Dependencies
-
-```php
-function resolveSchemaReferences(array $schema, array $definitions = []): array
-{
- // Recursively resolve $ref properties
- foreach ($schema as $key => $value) {
- if ($key === '$ref' && is_string($value)) {
- // Resolve reference to actual schema
- $refPath = str_replace('#/definitions/', '', $value);
- if (isset($definitions[$refPath])) {
- return $definitions[$refPath];
- }
- } elseif (is_array($value)) {
- $schema[$key] = resolveSchemaReferences($value, $definitions);
- }
- }
-
- return $schema;
-}
-```
-
-### 3. Version Compatibility Checking
-
-```php
-function checkVersionCompatibility(array $schema): void
-{
- $schemaVersion = $schema['$schema'] ?? '';
-
- $supportedVersions = [
- 'http://json-schema.org/draft-07/schema#',
- 'https://json-schema.org/draft/2019-09/schema',
- 'https://json-schema.org/draft/2020-12/schema'
- ];
-
- if ($schemaVersion && !in_array($schemaVersion, $supportedVersions)) {
- throw new InvalidArgumentException(
- "Unsupported schema version: {$schemaVersion}"
- );
- }
-}
-```
-
-### 4. Schema Caching
-
-```php
-class CachedSchemaLoader
-{
- private array $cache = [];
-
- public function load(string $filepath): Schema
- {
- $cacheKey = md5($filepath . filemtime($filepath));
-
- if (!isset($this->cache[$cacheKey])) {
- $this->cache[$cacheKey] = loadSchemaFromFile($filepath);
- }
-
- return $this->cache[$cacheKey];
- }
-}
-```
-
## Common Use Cases
@@ -370,22 +253,3 @@ class CachedSchemaLoader
Work with external JSON schemas from APIs, services, or documentation.
-
-## Next Steps
-
-
-
- Learn to validate data with imported schemas
-
-
- Explore the complete Schema Factory API reference
-
-
diff --git a/docs/json-schema/installation.mdx b/docs/json-schema/installation.mdx
index 4efef6d..e6aeb3b 100644
--- a/docs/json-schema/installation.mdx
+++ b/docs/json-schema/installation.mdx
@@ -13,15 +13,9 @@ icon: 'terminal'
- Install the package using Composer with one of these commands:
-
```bash
composer require cortexphp/json-schema
```
-
-
- Verify the package was installed by running: `composer show cortexphp/json-schema`
-
@@ -72,11 +66,3 @@ If you're contributing to the package or want to run tests:
## Next Steps
Now that you have the package installed, you're ready to create your first JSON Schema:
-
-
- Learn how to create and validate schemas with practical examples
-
diff --git a/docs/json-schema/introduction.mdx b/docs/json-schema/introduction.mdx
index 168f515..fedcd91 100644
--- a/docs/json-schema/introduction.mdx
+++ b/docs/json-schema/introduction.mdx
@@ -30,7 +30,6 @@ icon: 'book-open'
Validate data against schemas with detailed error messages and boolean validation methods.
@@ -70,7 +69,6 @@ icon: 'book-open'
Automatic validation of version-specific features with helpful error messages.
@@ -180,22 +178,3 @@ The package defaults to Draft 2020-12 for the latest features. Use Draft-07 for
| `unevaluatedProperties` | ❌ | ✅ | ✅ |
| `dependentSchemas` | ❌ | ✅ | ✅ |
| `prefixItems` | ❌ | ❌ | ✅ |
-
-## Next Steps
-
-
-
- Install the package and create your first schema
-
-
- Learn the basics with practical examples
-
-
diff --git a/docs/json-schema/mcp-server.mdx b/docs/json-schema/mcp-server.mdx
index 8e282ec..5199956 100644
--- a/docs/json-schema/mcp-server.mdx
+++ b/docs/json-schema/mcp-server.mdx
@@ -277,22 +277,3 @@ The MCP server provides access to comprehensive documentation, code examples, an
-## Additional Resources
-
-
-
- Browse the complete CortexPHP documentation
-
-
- Learn more about the Model Context Protocol
-
-
-
diff --git a/docs/json-schema/quickstart.mdx b/docs/json-schema/quickstart.mdx
index c6517b6..4ed42b3 100644
--- a/docs/json-schema/quickstart.mdx
+++ b/docs/json-schema/quickstart.mdx
@@ -172,9 +172,9 @@ Use `toArray()` when you need to programmatically work with the schema structure
$usernameSchema->isValid('john-doe'); // false (contains hyphen)
```
-
+
String schemas support patterns, length constraints, and format validation.
-
+
@@ -193,9 +193,9 @@ Use `toArray()` when you need to programmatically work with the schema structure
$tagsSchema->isValid([]); // false (too few items)
```
-
+
Array schemas can validate item types, count limits, and uniqueness.
-
+
@@ -215,9 +215,9 @@ Use `toArray()` when you need to programmatically work with the schema structure
);
```
-
+
Object schemas support unlimited nesting and property requirements.
-
+
@@ -227,7 +227,7 @@ You can also use schema classes directly instead of the factory:
-```php Factory Method (Recommended)
+```php Factory Method
use Cortex\JsonSchema\Schema;
$schema = Schema::string('name')
@@ -354,15 +354,4 @@ Schema::setDefaultVersion(SchemaVersion::Draft_07); // For maximum compatibility
>
Generate schemas automatically from PHP classes and functions
-
- Master data validation and error handling techniques
-
-
-
-The Schema class provides the most convenient way to create schemas. All examples in this documentation use the factory methods unless otherwise specified.
-
diff --git a/docs/json-schema/schema-types/array.mdx b/docs/json-schema/schema-types/array.mdx
index 5f43e62..604478f 100644
--- a/docs/json-schema/schema-types/array.mdx
+++ b/docs/json-schema/schema-types/array.mdx
@@ -535,22 +535,3 @@ try {
Validate complex nested structures like menu trees or organizational hierarchies.
-
-## Next Steps
-
-
-
- Learn about validating complex object structures
-
-
- Explore advanced array validation features in modern JSON Schema versions
-
-
diff --git a/docs/json-schema/schema-types/boolean.mdx b/docs/json-schema/schema-types/boolean.mdx
index c230d70..e17b6d8 100644
--- a/docs/json-schema/schema-types/boolean.mdx
+++ b/docs/json-schema/schema-types/boolean.mdx
@@ -400,22 +400,3 @@ $booleanSchema->isValid(false); // true
Track record states, completion status, and operational flags.
-
-## Next Steps
-
-
-
- Learn about null value validation
-
-
- Use booleans in conditional schema logic
-
-
diff --git a/docs/json-schema/schema-types/integer.mdx b/docs/json-schema/schema-types/integer.mdx
index 930d658..9e2cb16 100644
--- a/docs/json-schema/schema-types/integer.mdx
+++ b/docs/json-schema/schema-types/integer.mdx
@@ -366,22 +366,3 @@ try {
Validate integer configuration parameters like ports, timeouts, and limits.
-
-## Next Steps
-
-
-
- Learn about number validation for decimal values
-
-
- Validate boolean true/false values
-
-
diff --git a/docs/json-schema/schema-types/null.mdx b/docs/json-schema/schema-types/null.mdx
index 93d050d..a8f83bb 100644
--- a/docs/json-schema/schema-types/null.mdx
+++ b/docs/json-schema/schema-types/null.mdx
@@ -348,22 +348,3 @@ $processedDataSchema = Schema::object('processed_data')
Handle API fields that may not be present or applicable in all responses.
-
-## Next Steps
-
-
-
- Learn about combining multiple types including null
-
-
- Use null in conditional schema logic
-
-
diff --git a/docs/json-schema/schema-types/number.mdx b/docs/json-schema/schema-types/number.mdx
index 2a7d8a7..da7a345 100644
--- a/docs/json-schema/schema-types/number.mdx
+++ b/docs/json-schema/schema-types/number.mdx
@@ -295,7 +295,7 @@ try {
## Number vs Integer
-Numbers can be integers or floating-point values. If you specifically need integer validation, use [Integer Schema](/schema-types/integer) instead.
+Numbers can be integers or floating-point values. If you specifically need integer validation, use [Integer Schema](/json-schema/schema-types/integer) instead.
```php
@@ -328,22 +328,3 @@ $integerSchema->isValid(42.5); // false (not whole number)
Validate numeric configuration parameters with appropriate ranges and precision.
-
-## Next Steps
-
-
-
- Learn about integer-specific validation and constraints
-
-
- Validate arrays of numbers and other complex data structures
-
-
diff --git a/docs/json-schema/schema-types/object.mdx b/docs/json-schema/schema-types/object.mdx
index fe9473b..2f67720 100644
--- a/docs/json-schema/schema-types/object.mdx
+++ b/docs/json-schema/schema-types/object.mdx
@@ -519,6 +519,12 @@ $schema->isValid([
## Common Use Cases
+
+ Define schemas for LLM responses to ensure consistent, parseable structured data from AI models.
+
+
+ Specify function parameters for AI agents and assistants to enable reliable tool invocation.
+
Validate JSON API payloads with structured data and specific field requirements.
@@ -532,22 +538,3 @@ $schema->isValid([
Validate data models before persistence with property and constraint validation.
-
-## Next Steps
-
-
-
- Learn about array validation and nested data structures
-
-
- Explore pattern properties and advanced object validation
-
-
diff --git a/docs/json-schema/schema-types/string.mdx b/docs/json-schema/schema-types/string.mdx
index 60cb4c9..2b1a8aa 100644
--- a/docs/json-schema/schema-types/string.mdx
+++ b/docs/json-schema/schema-types/string.mdx
@@ -64,10 +64,6 @@ Set minimum and maximum character limits for your strings:
```
-
-Length constraints help ensure data fits database fields and meets business requirements.
-
-
## Pattern Matching
Use regular expressions to validate string patterns:
@@ -296,22 +292,3 @@ $uuidSchema = Schema::string('id', SchemaVersion::Draft_2019_09)
Validate imported text data against expected patterns and formats before processing.
-
-## Next Steps
-
-
-
- Learn about numeric validation with ranges and constraints
-
-
- Comprehensive guide to all available string formats
-
-
diff --git a/docs/json-schema/schema-types/union.mdx b/docs/json-schema/schema-types/union.mdx
index a7dfd2a..368da76 100644
--- a/docs/json-schema/schema-types/union.mdx
+++ b/docs/json-schema/schema-types/union.mdx
@@ -413,22 +413,3 @@ $shapeSchema = Schema::union([SchemaType::Object], 'shape')
Model data structures with multiple possible shapes or types.
-
-## Next Steps
-
-
-
- Learn advanced conditional logic with anyOf, oneOf, and allOf
-
-
- Master validation techniques for complex union types
-
-
diff --git a/docs/json-schema/validation/data-validation.mdx b/docs/json-schema/validation/data-validation.mdx
deleted file mode 100644
index 389e139..0000000
--- a/docs/json-schema/validation/data-validation.mdx
+++ /dev/null
@@ -1,241 +0,0 @@
----
-title: Data Validation
-description: 'Master data validation techniques with validate() and isValid() methods'
-icon: 'check'
----
-
-Data validation is the core functionality of JSON Schema. Learn how to validate data against your schemas, handle validation results, and work with validation errors effectively.
-
-## Basic Validation Methods
-
-Every schema provides two primary validation methods:
-
-```php
-use Cortex\JsonSchema\Schema;
-use Cortex\JsonSchema\Exceptions\SchemaException;
-
-$schema = Schema::string('name')
- ->minLength(2)
- ->maxLength(50)
- ->required();
-
-// Method 1: isValid() - returns boolean
-$isValid = $schema->isValid('John Doe'); // true
-$isValid = $schema->isValid('J'); // false
-
-// Method 2: validate() - throws exception on failure
-try {
- $schema->validate('John Doe');
- echo "Valid!";
-} catch (SchemaException $e) {
- echo "Invalid: " . $e->getMessage();
-}
-```
-
-## Using isValid() for Boolean Checks
-
-The `isValid()` method is perfect for simple true/false validation:
-
-```php
-$emailSchema = Schema::string('email')
- ->format(SchemaFormat::Email)
- ->required();
-
-$emails = [
- 'valid@example.com',
- 'invalid-email',
- 'another@test.org'
-];
-
-$validEmails = [];
-foreach ($emails as $email) {
- if ($emailSchema->isValid($email)) {
- $validEmails[] = $email;
- }
-}
-
-// $validEmails contains: ['valid@example.com', 'another@test.org']
-```
-
-### Conditional Logic with isValid()
-
-```php
-$userSchema = Schema::object('user')
- ->properties(
- Schema::string('name')->required(),
- Schema::integer('age')->minimum(18)->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required()
- );
-
-$userData = [
- 'name' => 'John Doe',
- 'age' => 25,
- 'email' => 'john@example.com'
-];
-
-if ($userSchema->isValid($userData)) {
- // Process valid user data
- echo "Processing user: " . $userData['name'];
-} else {
- // Handle invalid data
- echo "User data is invalid";
-}
-```
-
-## Using validate() for Detailed Error Information
-
-The `validate()` method throws descriptive exceptions when validation fails:
-
-```php
-$productSchema = Schema::object('product')
- ->properties(
- Schema::string('name')
- ->minLength(1)
- ->maxLength(100)
- ->required(),
- Schema::number('price')
- ->minimum(0)
- ->multipleOf(0.01)
- ->required(),
- Schema::array('tags')
- ->items(Schema::string())
- ->maxItems(10)
- )
- ->additionalProperties(false);
-
-$productData = [
- 'name' => '', // Too short
- 'price' => -10, // Below minimum
- 'tags' => ['electronics', 'mobile', /* 9 more tags */], // Too many items
- 'invalid_field' => 'not allowed' // Additional property
-];
-
-try {
- $productSchema->validate($productData);
-} catch (SchemaException $e) {
- echo "Validation error: " . $e->getMessage();
- // "String must have minimum length of 1"
-
- // Access detailed error information
- $errors = $e->getErrors();
- print_r($errors);
-}
-```
-
-## Validating Complex Data Structures
-
-### Object Validation
-
-```php
-$orderSchema = Schema::object('order')
- ->properties(
- Schema::string('id')->required(),
- Schema::object('customer')
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required()
- )
- ->required(),
- Schema::array('items')
- ->items(
- Schema::object()
- ->properties(
- Schema::string('sku')->required(),
- Schema::integer('quantity')->minimum(1)->required(),
- Schema::number('price')->minimum(0)->required()
- )
- )
- ->minItems(1)
- ->required()
- );
-
-$orderData = [
- 'id' => 'ORD-123',
- 'customer' => [
- 'name' => 'John Doe',
- 'email' => 'john@example.com'
- ],
- 'items' => [
- [
- 'sku' => 'PROD-001',
- 'quantity' => 2,
- 'price' => 29.99
- ],
- [
- 'sku' => 'PROD-002',
- 'quantity' => 1,
- 'price' => 15.50
- ]
- ]
-];
-
-if ($orderSchema->isValid($orderData)) {
- echo "Order is valid";
-} else {
- try {
- $orderSchema->validate($orderData);
- } catch (SchemaException $e) {
- echo "Order validation failed: " . $e->getMessage();
- }
-}
-```
-
-### Array Validation
-
-```php
-$scoresSchema = Schema::array('test_scores')
- ->items(
- Schema::object()
- ->properties(
- Schema::string('student_id')->required(),
- Schema::integer('score')
- ->minimum(0)
- ->maximum(100)
- ->required(),
- Schema::string('subject')
- ->enum(['math', 'science', 'english', 'history'])
- ->required()
- )
- )
- ->minItems(1)
- ->uniqueItems(true);
-
-$scoresData = [
- [
- 'student_id' => 'STU-001',
- 'score' => 95,
- 'subject' => 'math'
- ],
- [
- 'student_id' => 'STU-002',
- 'score' => 87,
- 'subject' => 'science'
- ]
-];
-
-try {
- $scoresSchema->validate($scoresData);
- echo "All scores are valid";
-} catch (SchemaException $e) {
- echo "Score validation error: " . $e->getMessage();
-}
-```
-
-## Next Steps
-
-
-
- Learn advanced error handling and custom exception management
-
-
- Explore the complete Schema Factory API reference
-
-
diff --git a/docs/json-schema/validation/error-handling.mdx b/docs/json-schema/validation/error-handling.mdx
deleted file mode 100644
index de37f01..0000000
--- a/docs/json-schema/validation/error-handling.mdx
+++ /dev/null
@@ -1,739 +0,0 @@
----
-title: Error Handling
-description: 'Advanced error handling and exception management for schema validation'
-icon: 'x'
----
-
-Master error handling in JSON Schema validation with detailed exception information, custom error messages, and graceful error recovery patterns.
-
-## SchemaException Overview
-
-All validation errors throw `SchemaException` with detailed information:
-
-```php
-use Cortex\JsonSchema\Schema;
-use Cortex\JsonSchema\Exceptions\SchemaException;
-
-$schema = Schema::string('email')
- ->format(SchemaFormat::Email)
- ->minLength(5)
- ->maxLength(100)
- ->required();
-
-try {
- $schema->validate('invalid-email-format');
-} catch (SchemaException $e) {
- echo "Error: " . $e->getMessage(); // User-friendly message
- echo "Code: " . $e->getCode(); // Error code
- echo "Property: " . $e->getProperty(); // Failed property (if available)
- echo "Value: " . $e->getFailedValue(); // Value that failed (if available)
-}
-```
-
-## Exception Types and Error Codes
-
-Different validation failures produce specific error codes:
-
-```php
-$userSchema = Schema::object('user')
- ->properties(
- Schema::string('name')
- ->minLength(2)
- ->maxLength(50)
- ->required(),
- Schema::string('email')
- ->format(SchemaFormat::Email)
- ->required(),
- Schema::integer('age')
- ->minimum(0)
- ->maximum(150)
- ->required()
- );
-
-// Test different error scenarios
-$testCases = [
- // Missing required field
- ['name' => 'John'],
-
- // String too short
- ['name' => 'J', 'email' => 'john@example.com', 'age' => 30],
-
- // Invalid format
- ['name' => 'John', 'email' => 'invalid-email', 'age' => 30],
-
- // Type mismatch
- ['name' => 'John', 'email' => 'john@example.com', 'age' => 'thirty'],
-
- // Value out of range
- ['name' => 'John', 'email' => 'john@example.com', 'age' => -5]
-];
-
-foreach ($testCases as $index => $testData) {
- try {
- $userSchema->validate($testData);
- echo "Test case {$index}: Valid\n";
- } catch (SchemaException $e) {
- echo "Test case {$index}: {$e->getMessage()}\n";
- echo " Error code: {$e->getCode()}\n";
- echo " Failed property: " . ($e->getProperty() ?? 'unknown') . "\n\n";
- }
-}
-```
-
-## Error Message Categories
-
-Schema validation errors fall into several categories:
-
-### Type Validation Errors
-
-```php
-$typeSchema = Schema::string('name');
-
-try {
- $typeSchema->validate(123); // Number instead of string
-} catch (SchemaException $e) {
- echo $e->getMessage(); // "Value must be a string"
- echo $e->getCode(); // Type validation error code
-}
-```
-
-### Format Validation Errors
-
-```php
-$emailSchema = Schema::string('email')->format(SchemaFormat::Email);
-
-try {
- $emailSchema->validate('not-an-email');
-} catch (SchemaException $e) {
- echo $e->getMessage(); // "Value must match the 'email' format"
-}
-```
-
-### Constraint Validation Errors
-
-```php
-$lengthSchema = Schema::string('username')
- ->minLength(3)
- ->maxLength(20);
-
-try {
- $lengthSchema->validate('ab'); // Too short
-} catch (SchemaException $e) {
- echo $e->getMessage(); // "String must have minimum length of 3"
-}
-
-try {
- $lengthSchema->validate('very_long_username_that_exceeds_limit');
-} catch (SchemaException $e) {
- echo $e->getMessage(); // "String must have maximum length of 20"
-}
-```
-
-### Required Field Errors
-
-```php
-$requiredSchema = Schema::object('user')
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->required()
- );
-
-try {
- $requiredSchema->validate(['name' => 'John']); // Missing email
-} catch (SchemaException $e) {
- echo $e->getMessage(); // "Property 'email' is required"
- echo $e->getProperty(); // "email"
-}
-```
-
-## Custom Error Messages
-
-Create user-friendly error messages for different contexts:
-
-```php
-class UserFriendlyErrorHandler
-{
- private array $messageMap = [
- // Type errors
- 'must be a string' => 'Please enter text for this field',
- 'must be an integer' => 'Please enter a whole number',
- 'must be a number' => 'Please enter a valid number',
- 'must be a boolean' => 'Please select yes or no',
-
- // Format errors
- 'must match the \'email\' format' => 'Please enter a valid email address',
- 'must match the \'uri\' format' => 'Please enter a valid URL',
- 'must match the \'date\' format' => 'Please enter a valid date (YYYY-MM-DD)',
-
- // Constraint errors
- 'must have minimum length' => 'This field is too short',
- 'must have maximum length' => 'This field is too long',
- 'must be greater than or equal to' => 'Value is too small',
- 'must be less than or equal to' => 'Value is too large',
-
- // Required field errors
- 'is required' => 'This field is required',
- ];
-
- public function getFriendlyMessage(SchemaException $e): string
- {
- $originalMessage = $e->getMessage();
-
- foreach ($this->messageMap as $pattern => $friendlyMessage) {
- if (strpos($originalMessage, $pattern) !== false) {
- return $friendlyMessage;
- }
- }
-
- return $originalMessage; // Fallback to original message
- }
-
- public function getFieldSpecificMessage(SchemaException $e): string
- {
- $property = $e->getProperty();
- $friendlyMessage = $this->getFriendlyMessage($e);
-
- if ($property) {
- $fieldName = ucfirst(str_replace('_', ' ', $property));
- return "{$fieldName}: {$friendlyMessage}";
- }
-
- return $friendlyMessage;
- }
-}
-
-// Usage
-$errorHandler = new UserFriendlyErrorHandler();
-
-try {
- $userSchema->validate(['name' => 'J', 'email' => 'invalid']);
-} catch (SchemaException $e) {
- echo "Technical: " . $e->getMessage() . "\n";
- echo "User-friendly: " . $errorHandler->getFriendlyMessage($e) . "\n";
- echo "Field-specific: " . $errorHandler->getFieldSpecificMessage($e) . "\n";
-}
-```
-
-## Validation Result Objects
-
-Create structured validation results for better error handling:
-
-```php
-class ValidationResult
-{
- public function __construct(
- public bool $isValid,
- public array $errors = [],
- public ?array $data = null
- ) {}
-
- public function hasErrors(): bool
- {
- return !empty($this->errors);
- }
-
- public function getFirstError(): ?string
- {
- return $this->errors[0] ?? null;
- }
-
- public function getErrorsForField(string $field): array
- {
- return array_filter($this->errors, fn($error) =>
- isset($error['field']) && $error['field'] === $field
- );
- }
-}
-
-class ValidatorWithResults
-{
- public function validate(Schema $schema, mixed $data): ValidationResult
- {
- if ($schema->isValid($data)) {
- return new ValidationResult(true, [], $data);
- }
-
- $errors = [];
- try {
- $schema->validate($data);
- } catch (SchemaException $e) {
- $errors[] = [
- 'message' => $e->getMessage(),
- 'code' => $e->getCode(),
- 'field' => $e->getProperty(),
- 'value' => $e->getFailedValue()
- ];
- }
-
- return new ValidationResult(false, $errors, $data);
- }
-
- public function validateMultiple(Schema $schema, array $items): array
- {
- $results = [];
-
- foreach ($items as $index => $item) {
- $results[$index] = $this->validate($schema, $item);
- }
-
- return $results;
- }
-}
-
-// Usage
-$validator = new ValidatorWithResults();
-$userSchema = Schema::object('user')
- ->properties(
- Schema::string('name')->minLength(2)->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required()
- );
-
-$result = $validator->validate($userSchema, ['name' => 'J']);
-
-if (!$result->isValid) {
- echo "Validation failed:\n";
- foreach ($result->errors as $error) {
- echo "- {$error['message']}\n";
- }
-}
-```
-
-## Nested Object Error Handling
-
-Handle errors in complex nested structures:
-
-```php
-class NestedErrorHandler
-{
- public function validateWithPath(Schema $schema, mixed $data, string $path = ''): array
- {
- $errors = [];
-
- try {
- $schema->validate($data);
- } catch (SchemaException $e) {
- $fieldPath = $path;
- if ($e->getProperty()) {
- $fieldPath .= ($fieldPath ? '.' : '') . $e->getProperty();
- }
-
- $errors[] = [
- 'path' => $fieldPath,
- 'message' => $e->getMessage(),
- 'value' => $e->getFailedValue()
- ];
- }
-
- return $errors;
- }
-
- public function validateObject(Schema $schema, array $data, string $basePath = ''): array
- {
- $allErrors = [];
-
- // First validate the entire object
- $errors = $this->validateWithPath($schema, $data, $basePath);
- $allErrors = array_merge($allErrors, $errors);
-
- // If the object validation passes, validate individual properties
- if (empty($errors) && is_array($data)) {
- $schemaArray = $schema->toArray();
-
- if (isset($schemaArray['properties'])) {
- foreach ($schemaArray['properties'] as $property => $propSchema) {
- if (isset($data[$property])) {
- $propertyPath = $basePath . ($basePath ? '.' : '') . $property;
- $propertySchema = Schema::fromJson($propSchema);
-
- $propertyErrors = $this->validateWithPath(
- $propertySchema,
- $data[$property],
- $propertyPath
- );
-
- $allErrors = array_merge($allErrors, $propertyErrors);
- }
- }
- }
- }
-
- return $allErrors;
- }
-}
-
-// Complex nested schema
-$orderSchema = Schema::object('order')
- ->properties(
- Schema::string('id')->required(),
- Schema::object('customer')
- ->properties(
- Schema::string('name')->minLength(2)->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required(),
- Schema::object('address')
- ->properties(
- Schema::string('street')->required(),
- Schema::string('city')->required(),
- Schema::string('postal_code')
- ->pattern('^\d{5}$')
- ->required()
- )
- ->required()
- )
- ->required(),
- Schema::array('items')
- ->items(
- Schema::object()
- ->properties(
- Schema::string('sku')->required(),
- Schema::integer('quantity')->minimum(1)->required()
- )
- )
- ->minItems(1)
- ->required()
- );
-
-$nestedHandler = new NestedErrorHandler();
-
-$invalidOrder = [
- 'id' => 'ORD-123',
- 'customer' => [
- 'name' => 'J', // Too short
- 'email' => 'invalid-email', // Invalid format
- 'address' => [
- 'street' => '123 Main St',
- // Missing city
- 'postal_code' => '1234' // Invalid format
- ]
- ],
- 'items' => [
- [
- 'sku' => 'ITEM-001',
- 'quantity' => 0 // Below minimum
- ]
- ]
-];
-
-$errors = $nestedHandler->validateObject($orderSchema, $invalidOrder);
-
-foreach ($errors as $error) {
- echo "Error at {$error['path']}: {$error['message']}\n";
-}
-```
-
-## Error Recovery and Suggestions
-
-Provide helpful suggestions for common validation errors:
-
-```php
-class ErrorRecoveryHelper
-{
- public function suggestCorrections(SchemaException $e): array
- {
- $suggestions = [];
- $message = $e->getMessage();
- $value = $e->getFailedValue();
-
- // Email format suggestions
- if (strpos($message, 'email') !== false && is_string($value)) {
- if (!strpos($value, '@')) {
- $suggestions[] = "Add an '@' symbol to your email address";
- } elseif (!strpos($value, '.')) {
- $suggestions[] = "Add a domain extension like '.com' to your email";
- }
- }
-
- // String length suggestions
- if (strpos($message, 'minimum length') !== false) {
- preg_match('/minimum length of (\d+)/', $message, $matches);
- if ($matches) {
- $required = (int)$matches[1];
- $current = is_string($value) ? strlen($value) : 0;
- $needed = $required - $current;
- $suggestions[] = "Add {$needed} more character" . ($needed > 1 ? 's' : '');
- }
- }
-
- if (strpos($message, 'maximum length') !== false) {
- preg_match('/maximum length of (\d+)/', $message, $matches);
- if ($matches) {
- $allowed = (int)$matches[1];
- $current = is_string($value) ? strlen($value) : 0;
- $excess = $current - $allowed;
- $suggestions[] = "Remove {$excess} character" . ($excess > 1 ? 's' : '');
- }
- }
-
- // Numeric range suggestions
- if (strpos($message, 'greater than or equal to') !== false) {
- preg_match('/greater than or equal to ([\d.]+)/', $message, $matches);
- if ($matches) {
- $minimum = $matches[1];
- $suggestions[] = "Enter a value of {$minimum} or higher";
- }
- }
-
- // Enum suggestions
- if (strpos($message, 'must be one of') !== false) {
- $suggestions[] = "Choose from the available options";
- }
-
- return $suggestions;
- }
-
- public function getDetailedError(SchemaException $e): array
- {
- return [
- 'message' => $e->getMessage(),
- 'code' => $e->getCode(),
- 'field' => $e->getProperty(),
- 'value' => $e->getFailedValue(),
- 'suggestions' => $this->suggestCorrections($e)
- ];
- }
-}
-
-// Usage
-$recoveryHelper = new ErrorRecoveryHelper();
-
-try {
- $emailSchema = Schema::string('email')->format(SchemaFormat::Email);
- $emailSchema->validate('userexample.com'); // Missing @
-} catch (SchemaException $e) {
- $detailedError = $recoveryHelper->getDetailedError($e);
-
- echo "Error: {$detailedError['message']}\n";
- if (!empty($detailedError['suggestions'])) {
- echo "Suggestions:\n";
- foreach ($detailedError['suggestions'] as $suggestion) {
- echo "- {$suggestion}\n";
- }
- }
-}
-```
-
-## Bulk Validation Error Handling
-
-Handle errors when validating multiple items:
-
-```php
-class BulkValidator
-{
- public function validateBatch(Schema $schema, array $items): array
- {
- $results = [];
-
- foreach ($items as $index => $item) {
- try {
- $schema->validate($item);
- $results[$index] = [
- 'valid' => true,
- 'data' => $item,
- 'errors' => []
- ];
- } catch (SchemaException $e) {
- $results[$index] = [
- 'valid' => false,
- 'data' => $item,
- 'errors' => [
- [
- 'message' => $e->getMessage(),
- 'field' => $e->getProperty(),
- 'code' => $e->getCode()
- ]
- ]
- ];
- }
- }
-
- return $results;
- }
-
- public function getValidItems(array $batchResults): array
- {
- $validItems = [];
-
- foreach ($batchResults as $index => $result) {
- if ($result['valid']) {
- $validItems[$index] = $result['data'];
- }
- }
-
- return $validItems;
- }
-
- public function getErrorSummary(array $batchResults): array
- {
- $summary = [
- 'total' => count($batchResults),
- 'valid' => 0,
- 'invalid' => 0,
- 'error_types' => []
- ];
-
- foreach ($batchResults as $result) {
- if ($result['valid']) {
- $summary['valid']++;
- } else {
- $summary['invalid']++;
-
- foreach ($result['errors'] as $error) {
- $errorType = $error['message'];
- $summary['error_types'][$errorType] =
- ($summary['error_types'][$errorType] ?? 0) + 1;
- }
- }
- }
-
- return $summary;
- }
-}
-
-// Usage
-$bulkValidator = new BulkValidator();
-$userSchema = Schema::object('user')
- ->properties(
- Schema::string('name')->minLength(2)->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required()
- );
-
-$users = [
- ['name' => 'John Doe', 'email' => 'john@example.com'], // Valid
- ['name' => 'J', 'email' => 'jane@example.com'], // Invalid name
- ['name' => 'Bob Smith', 'email' => 'invalid-email'], // Invalid email
- ['name' => 'Alice Johnson', 'email' => 'alice@example.com'] // Valid
-];
-
-$results = $bulkValidator->validateBatch($userSchema, $users);
-$validUsers = $bulkValidator->getValidItems($results);
-$summary = $bulkValidator->getErrorSummary($results);
-
-echo "Validation Summary:\n";
-echo "Total: {$summary['total']}\n";
-echo "Valid: {$summary['valid']}\n";
-echo "Invalid: {$summary['invalid']}\n";
-
-if (!empty($summary['error_types'])) {
- echo "\nError Types:\n";
- foreach ($summary['error_types'] as $errorType => $count) {
- echo "- {$errorType}: {$count} occurrence(s)\n";
- }
-}
-```
-
-## Best Practices
-
-### 1. Use Specific Error Messages
-
-```php
-// Good: Specific validation rules with clear error context
-$passwordSchema = Schema::string('password')
- ->minLength(8)
- ->pattern('(?=.*[a-z])(?=.*[A-Z])(?=.*\d)')
- ->description('Password must be at least 8 characters with uppercase, lowercase, and number');
-
-// Provide context in error handling
-try {
- $passwordSchema->validate($password);
-} catch (SchemaException $e) {
- $errorContext = [
- 'field' => 'password',
- 'message' => $e->getMessage(),
- 'requirements' => 'At least 8 characters with uppercase, lowercase, and number'
- ];
-}
-```
-
-### 2. Log Validation Errors
-
-```php
-class ValidatorWithLogging
-{
- private LoggerInterface $logger;
-
- public function validateWithLogging(Schema $schema, mixed $data, array $context = []): bool
- {
- try {
- $schema->validate($data);
- return true;
- } catch (SchemaException $e) {
- $this->logger->warning('Schema validation failed', [
- 'message' => $e->getMessage(),
- 'code' => $e->getCode(),
- 'field' => $e->getProperty(),
- 'context' => $context
- ]);
-
- return false;
- }
- }
-}
-```
-
-### 3. Graceful Degradation
-
-```php
-function processUserDataSafely(array $userData): array
-{
- $userSchema = Schema::object('user')
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->format(SchemaFormat::Email)->required()
- );
-
- try {
- $userSchema->validate($userData);
- return ['status' => 'success', 'data' => $userData];
- } catch (SchemaException $e) {
- // Log error but continue with partial processing
- error_log("User data validation failed: " . $e->getMessage());
-
- // Return what we can process safely
- $safeData = [];
- if (isset($userData['name']) && is_string($userData['name'])) {
- $safeData['name'] = $userData['name'];
- }
-
- return [
- 'status' => 'partial',
- 'data' => $safeData,
- 'errors' => [$e->getMessage()]
- ];
- }
-}
-```
-
-## Common Use Cases
-
-
-
- Provide user-friendly error messages and suggestions for form input validation.
-
-
- Structure detailed error responses for API endpoints with validation failures.
-
-
- Handle validation errors during bulk data import with detailed error reporting.
-
-
- Provide helpful error messages for application configuration validation.
-
-
-
-## Next Steps
-
-
-
- Learn about version-specific validation features and compatibility
-
-
- Master the core validation methods and techniques
-
-
diff --git a/docs/json-schema/validation/version-features.mdx b/docs/json-schema/validation/version-features.mdx
deleted file mode 100644
index ee09d65..0000000
--- a/docs/json-schema/validation/version-features.mdx
+++ /dev/null
@@ -1,636 +0,0 @@
----
-title: Version Feature Validation
-description: 'Automatic validation of JSON Schema version compatibility and feature support'
-icon: 'ticket-check'
----
-
-The package automatically validates that schema features are compatible with the specified JSON Schema version, preventing runtime errors and ensuring schema portability across different validators.
-
-## Automatic Feature Validation
-
-When you use features that require specific JSON Schema versions, the package automatically validates compatibility:
-
-```php
-use Cortex\JsonSchema\Schema;
-use Cortex\JsonSchema\Enums\SchemaVersion;
-use Cortex\JsonSchema\Exceptions\SchemaException;
-
-// ✅ This works - deprecated is supported in Draft 2019-09+
-$modernSchema = Schema::string('legacy_field', SchemaVersion::Draft_2019_09)
- ->deprecated()
- ->comment('Use new_field instead');
-
-// ❌ This throws an exception - deprecated requires Draft 2019-09+
-try {
- $invalidSchema = Schema::string('legacy_field', SchemaVersion::Draft_07)
- ->deprecated(); // SchemaException thrown here
-} catch (SchemaException $e) {
- echo $e->getMessage();
- // "Feature 'Property deprecation annotation' is not supported in Draft 7.
- // Minimum version required: Draft 2019-09."
-}
-```
-
-## Feature Support Matrix
-
-Understanding which features are available in each JSON Schema version:
-
-### Core Validation (All Versions)
-
-```php
-// These features work in all supported versions
-$basicSchema = Schema::object('basic', SchemaVersion::Draft_07)
- ->properties(
- Schema::string('name')
- ->minLength(2)
- ->maxLength(100)
- ->pattern('^[A-Za-z\s]+$')
- ->required(),
- Schema::integer('age')
- ->minimum(0)
- ->maximum(150)
- ->required(),
- Schema::array('tags')
- ->items(Schema::string())
- ->minItems(1)
- ->maxItems(10)
- ->uniqueItems(true)
- )
- ->additionalProperties(false);
-```
-
-### Conditional Logic (Draft-07+)
-
-```php
-// if/then/else works in Draft-07 and later
-$conditionalSchema = Schema::object('user', SchemaVersion::Draft_07)
- ->properties(
- Schema::string('type')->enum(['personal', 'business']),
- Schema::string('company_name'),
- Schema::string('tax_id')
- )
- ->if(
- Schema::object()->properties(
- Schema::string('type')->const('business')
- )
- )
- ->then(
- Schema::object()->properties(
- Schema::string('company_name')->required(),
- Schema::string('tax_id')->required()
- )
- );
-```
-
-### Draft 2019-09 Features
-
-```php
-// Advanced features requiring Draft 2019-09+
-$modernSchema = Schema::object('modern_user', SchemaVersion::Draft_2019_09)
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->required(),
-
- // Deprecated annotation
- Schema::string('old_email')
- ->deprecated()
- ->comment('Use email field instead'),
-
- // Array contains validation
- Schema::array('roles')
- ->items(Schema::string())
- ->minContains(1) // At least one role required
- ->maxContains(5), // Maximum 5 roles
-
- // Extended format support
- Schema::string('id')
- ->format(SchemaFormat::Uuid),
-
- Schema::string('session_duration')
- ->format(SchemaFormat::Duration)
- )
- // Unevaluated properties
- ->unevaluatedProperties(false)
-
- // Dependent schemas
- ->dependentSchema('old_email',
- Schema::object()
- ->if(Schema::object()->properties(
- Schema::string('old_email')->minLength(1)
- ))
- ->then(Schema::object()
- ->properties(
- Schema::string('migration_date')
- ->format(SchemaFormat::Date)
- ->required()
- )
- )
- );
-```
-
-### Draft 2020-12 Features
-
-```php
-// Cutting-edge features in Draft 2020-12
-$latestSchema = Schema::array('tuple_array', SchemaVersion::Draft_2020_12)
- // Prefix items for tuple validation
- ->prefixItems([
- Schema::string()->description('Name'),
- Schema::integer()->minimum(0)->description('Age'),
- Schema::boolean()->description('Active status')
- ])
- // Additional items after prefix
- ->items(Schema::string()->description('Additional info'))
- // Unevaluated items control
- ->unevaluatedItems(false);
-```
-
-## Version Detection and Error Messages
-
-The package provides clear error messages when incompatible features are used:
-
-```php
-function demonstrateVersionErrors()
-{
- $examples = [
- 'Deprecated annotation' => function() {
- return Schema::string('field', SchemaVersion::Draft_07)
- ->deprecated();
- },
-
- 'Min/Max contains' => function() {
- return Schema::array('items', SchemaVersion::Draft_07)
- ->minContains(1);
- },
-
- 'UUID format' => function() {
- return Schema::string('id', SchemaVersion::Draft_07)
- ->format(SchemaFormat::Uuid);
- },
-
- 'Unevaluated properties' => function() {
- return Schema::object('strict', SchemaVersion::Draft_07)
- ->unevaluatedProperties(false);
- },
-
- 'Dependent schemas' => function() {
- return Schema::object('conditional', SchemaVersion::Draft_07)
- ->dependentSchema('field', Schema::object());
- }
- ];
-
- foreach ($examples as $featureName => $schemaBuilder) {
- try {
- $schemaBuilder();
- echo "✅ {$featureName}: Compatible\n";
- } catch (SchemaException $e) {
- echo "❌ {$featureName}: {$e->getMessage()}\n";
- }
- }
-}
-
-demonstrateVersionErrors();
-```
-
-## Feature Detection
-
-Check feature support programmatically:
-
-```php
-use Cortex\JsonSchema\Enums\SchemaFeature;
-
-/**
- * Check if a feature is supported in a specific version
- */
-function checkFeatureSupport(SchemaVersion $version, SchemaFeature $feature): bool
-{
- return $version->supports($feature);
-}
-
-/**
- * Get minimum version required for a feature
- */
-function getMinimumVersion(SchemaFeature $feature): SchemaVersion
-{
- return $feature->getMinimumVersion();
-}
-
-// Feature compatibility checking
-$features = [
- SchemaFeature::Deprecated,
- SchemaFeature::MinContains,
- SchemaFeature::MaxContains,
- SchemaFeature::UnevaluatedProperties,
- SchemaFeature::DependentSchemas,
- SchemaFeature::PrefixItems
-];
-
-foreach ($features as $feature) {
- $minVersion = getMinimumVersion($feature);
- $description = $feature->getDescription();
-
- echo "Feature: {$description}\n";
- echo "Minimum version: {$minVersion->name}\n";
- echo "Supported in Draft-07: " .
- (checkFeatureSupport(SchemaVersion::Draft_07, $feature) ? 'Yes' : 'No') . "\n";
- echo "Supported in Draft 2019-09: " .
- (checkFeatureSupport(SchemaVersion::Draft_2019_09, $feature) ? 'Yes' : 'No') . "\n";
- echo "Supported in Draft 2020-12: " .
- (checkFeatureSupport(SchemaVersion::Draft_2020_12, $feature) ? 'Yes' : 'No') . "\n\n";
-}
-```
-
-## Schema Migration Between Versions
-
-Migrate schemas to take advantage of newer features:
-
-```php
-class SchemaMigrator
-{
- public function upgradeToDraft201909(Schema $draft07Schema): Schema
- {
- $schemaArray = $draft07Schema->toArray();
-
- // Update schema version
- $schemaArray['$schema'] = 'https://json-schema.org/draft/2019-09/schema';
-
- // Convert definitions to $defs
- if (isset($schemaArray['definitions'])) {
- $schemaArray['$defs'] = $schemaArray['definitions'];
- unset($schemaArray['definitions']);
-
- // Update $ref paths
- $schemaArray = $this->updateRefPaths($schemaArray);
- }
-
- return Schema::fromJson($schemaArray, SchemaVersion::Draft_2019_09);
- }
-
- public function addModernFeatures(Schema $basicSchema): Schema
- {
- $schemaArray = $basicSchema->toArray();
-
- // Ensure we're using a modern version
- if (!isset($schemaArray['$schema']) ||
- strpos($schemaArray['$schema'], '2019-09') === false) {
- $schemaArray['$schema'] = 'https://json-schema.org/draft/2019-09/schema';
- }
-
- // Add modern validation features
- if ($schemaArray['type'] === 'object') {
- // Add strict property validation
- $schemaArray['unevaluatedProperties'] = false;
-
- // Add examples for better documentation
- if (isset($schemaArray['properties'])) {
- foreach ($schemaArray['properties'] as $prop => &$propSchema) {
- if ($propSchema['type'] === 'string' && !isset($propSchema['examples'])) {
- $propSchema['examples'] = ["example_{$prop}"];
- }
- }
- }
- }
-
- return Schema::fromJson($schemaArray, SchemaVersion::Draft_2019_09);
- }
-
- private function updateRefPaths(array $schema): array
- {
- foreach ($schema as $key => &$value) {
- if ($key === '$ref' && is_string($value)) {
- $value = str_replace('#/definitions/', '#/$defs/', $value);
- } elseif (is_array($value)) {
- $value = $this->updateRefPaths($value);
- }
- }
-
- return $schema;
- }
-}
-
-// Usage example
-$migrator = new SchemaMigrator();
-
-// Original Draft-07 schema
-$originalSchema = Schema::object('user', SchemaVersion::Draft_07)
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->required()
- )
- ->addDefinition('address',
- Schema::object()
- ->properties(
- Schema::string('street')->required(),
- Schema::string('city')->required()
- )
- );
-
-// Upgrade to take advantage of Draft 2019-09 features
-$modernSchema = $migrator->upgradeToDraft201909($originalSchema);
-$enhancedSchema = $migrator->addModernFeatures($modernSchema);
-
-// Now we can use modern features
-$enhancedSchema = $enhancedSchema
- ->unevaluatedProperties(false) // This now works
- ->properties(
- Schema::string('legacy_field')
- ->deprecated() // This now works too
- );
-```
-
-## Conditional Feature Usage
-
-Use features conditionally based on version support:
-
-```php
-class VersionAwareSchemaBuilder
-{
- public function buildUserSchema(SchemaVersion $version): Schema
- {
- $schema = Schema::object('user', $version)
- ->properties(
- Schema::string('name')->required(),
- Schema::string('email')->required()
- );
-
- // Add version-specific features
- if ($version->supports(SchemaFeature::Deprecated)) {
- $schema = $schema->properties(
- Schema::string('old_email')
- ->deprecated()
- ->comment('Use email field instead')
- );
- }
-
- if ($version->supports(SchemaFeature::UnevaluatedProperties)) {
- $schema = $schema->unevaluatedProperties(false);
- }
-
- if ($version->supports(SchemaFeature::MinContains)) {
- $schema = $schema->properties(
- Schema::array('roles')
- ->items(Schema::string())
- ->minContains(1)
- ->maxContains(5)
- );
- } else {
- // Fallback for older versions
- $schema = $schema->properties(
- Schema::array('roles')
- ->items(Schema::string())
- ->minItems(1)
- ->maxItems(5)
- );
- }
-
- return $schema;
- }
-
- public function buildWithBestFeatures(SchemaVersion $targetVersion): Schema
- {
- // Use the most advanced features available
- $availableFeatures = [
- SchemaFeature::Deprecated,
- SchemaFeature::UnevaluatedProperties,
- SchemaFeature::MinContains,
- SchemaFeature::DependentSchemas
- ];
-
- $schema = Schema::object('advanced_user', $targetVersion)
- ->properties(
- Schema::string('username')->required(),
- Schema::string('email')->required()
- );
-
- foreach ($availableFeatures as $feature) {
- if ($targetVersion->supports($feature)) {
- $schema = $this->addFeatureToSchema($schema, $feature);
- }
- }
-
- return $schema;
- }
-
- private function addFeatureToSchema(Schema $schema, SchemaFeature $feature): Schema
- {
- switch ($feature) {
- case SchemaFeature::Deprecated:
- return $schema->properties(
- Schema::string('legacy_username')
- ->deprecated()
- ->comment('Use username instead')
- );
-
- case SchemaFeature::UnevaluatedProperties:
- return $schema->unevaluatedProperties(false);
-
- case SchemaFeature::MinContains:
- return $schema->properties(
- Schema::array('permissions')
- ->items(Schema::string())
- ->minContains(1)
- );
-
- case SchemaFeature::DependentSchemas:
- return $schema->dependentSchema('legacy_username',
- Schema::object()
- ->properties(
- Schema::string('migration_date')
- ->format(SchemaFormat::Date)
- ->required()
- )
- );
-
- default:
- return $schema;
- }
- }
-}
-
-// Usage
-$builder = new VersionAwareSchemaBuilder();
-
-// Build schemas for different target environments
-$draft07Schema = $builder->buildUserSchema(SchemaVersion::Draft_07);
-$modernSchema = $builder->buildUserSchema(SchemaVersion::Draft_2019_09);
-$latestSchema = $builder->buildUserSchema(SchemaVersion::Draft_2020_12);
-
-// Each schema uses the best features available for its version
-```
-
-## Validation Environment Detection
-
-Detect and adapt to different validation environments:
-
-```php
-class EnvironmentAwareValidator
-{
- private SchemaVersion $supportedVersion;
-
- public function __construct()
- {
- $this->supportedVersion = $this->detectEnvironmentVersion();
- }
-
- private function detectEnvironmentVersion(): SchemaVersion
- {
- // In a real application, you might:
- // - Check client capabilities
- // - Read from configuration
- // - Test feature support
-
- // For demo, assume based on PHP version or configuration
- $configVersion = $_ENV['JSON_SCHEMA_VERSION'] ?? 'draft-2020-12';
-
- return match($configVersion) {
- 'draft-07' => SchemaVersion::Draft_07,
- 'draft-2019-09' => SchemaVersion::Draft_2019_09,
- default => SchemaVersion::Draft_2020_12
- };
- }
-
- public function createCompatibleSchema(array $requirements): Schema
- {
- $schema = Schema::object('dynamic', $this->supportedVersion);
-
- foreach ($requirements as $field => $config) {
- $fieldSchema = $this->createFieldSchema($config);
- $schema = $schema->properties($fieldSchema->propertyName($field));
- }
-
- // Add version-appropriate constraints
- if ($this->supportedVersion->supports(SchemaFeature::UnevaluatedProperties)) {
- $schema = $schema->unevaluatedProperties(false);
- } else {
- $schema = $schema->additionalProperties(false);
- }
-
- return $schema;
- }
-
- private function createFieldSchema(array $config): Schema
- {
- $type = $config['type'] ?? 'string';
- $fieldSchema = match($type) {
- 'string' => Schema::string(),
- 'integer' => Schema::integer(),
- 'number' => Schema::number(),
- 'boolean' => Schema::boolean(),
- 'array' => Schema::array(),
- default => Schema::string()
- };
-
- // Apply constraints based on version support
- if (isset($config['deprecated']) &&
- $this->supportedVersion->supports(SchemaFeature::Deprecated)) {
- $fieldSchema = $fieldSchema->deprecated();
- }
-
- if (isset($config['format'])) {
- $format = SchemaFormat::from($config['format']);
- if ($this->isFormatSupported($format)) {
- $fieldSchema = $fieldSchema->format($format);
- }
- }
-
- return $fieldSchema;
- }
-
- private function isFormatSupported(SchemaFormat $format): bool
- {
- $modernFormats = [SchemaFormat::Uuid, SchemaFormat::Duration];
-
- if (in_array($format, $modernFormats)) {
- return $this->supportedVersion->supports(SchemaFeature::ExtendedFormats);
- }
-
- return true; // Basic formats supported in all versions
- }
-}
-```
-
-## Best Practices
-
-### 1. Use Version Detection
-
-```php
-// Good: Check version support before using features
-if (SchemaVersion::Draft_2019_09->supports(SchemaFeature::Deprecated)) {
- $schema = $schema->deprecated();
-}
-
-// Avoid: Assuming feature support
-$schema = $schema->deprecated(); // May fail in older versions
-```
-
-### 2. Provide Fallbacks
-
-```php
-// Good: Provide fallbacks for unsupported features
-function addStrictValidation(Schema $schema, SchemaVersion $version): Schema
-{
- if ($version->supports(SchemaFeature::UnevaluatedProperties)) {
- return $schema->unevaluatedProperties(false);
- } else {
- return $schema->additionalProperties(false);
- }
-}
-```
-
-### 3. Document Version Requirements
-
-```php
-/**
- * Create a modern user schema with advanced validation
- *
- * @param SchemaVersion $version Must be Draft 2019-09 or later for full features
- * @throws SchemaException If version doesn't support required features
- */
-function createAdvancedUserSchema(SchemaVersion $version): Schema
-{
- if (!$version->supports(SchemaFeature::UnevaluatedProperties)) {
- throw new SchemaException(
- "Advanced user schema requires Draft 2019-09 or later"
- );
- }
-
- return Schema::object('advanced_user', $version)
- ->unevaluatedProperties(false);
-}
-```
-
-## Common Use Cases
-
-
-
- Adapt schema validation based on API version and client capabilities.
-
-
- Start with basic validation and add advanced features when supported.
-
-
- Ensure schema compatibility across different JSON Schema validators.
-
-
- Migrate schemas to newer versions while maintaining backward compatibility.
-
-
-
-## Next Steps
-
-
-
- Learn more about JSON Schema version differences and capabilities
-
-
- Explore the complete API reference and method documentation
-
-
diff --git a/src/Contracts/JsonSchema.php b/src/Contracts/JsonSchema.php
index 6b8c37d..3a2d2c8 100644
--- a/src/Contracts/JsonSchema.php
+++ b/src/Contracts/JsonSchema.php
@@ -18,6 +18,11 @@ public function title(string $title): static;
*/
public function getTitle(): ?string;
+ /**
+ * Determine if the schema has a title
+ */
+ public function hasTitle(): bool;
+
/**
* Set the description
*/
diff --git a/src/Types/Concerns/HasProperties.php b/src/Types/Concerns/HasProperties.php
index a8c9b83..1a3d82c 100644
--- a/src/Types/Concerns/HasProperties.php
+++ b/src/Types/Concerns/HasProperties.php
@@ -254,7 +254,11 @@ public function hasRequiredProperties(): bool
public function requireAll(): static
{
foreach ($this->properties as $property) {
- $property->required();
+ $title = $property->getTitle();
+
+ if ($title !== null) {
+ $this->requiredProperties[] = $title;
+ }
}
return $this;
diff --git a/src/Types/Concerns/HasTitle.php b/src/Types/Concerns/HasTitle.php
index 21402ce..55f13ce 100644
--- a/src/Types/Concerns/HasTitle.php
+++ b/src/Types/Concerns/HasTitle.php
@@ -27,6 +27,14 @@ public function getTitle(): ?string
return $this->title;
}
+ /**
+ * Determine if the schema has a title
+ */
+ public function hasTitle(): bool
+ {
+ return $this->title !== null;
+ }
+
/**
* Add title to schema array
*