diff --git a/docs/json-schema/code-generation/from-classes.mdx b/docs/json-schema/code-generation/from-classes.mdx index dd92a73..4571aa9 100644 --- a/docs/json-schema/code-generation/from-classes.mdx +++ b/docs/json-schema/code-generation/from-classes.mdx @@ -188,7 +188,7 @@ class ModernUser // Generate with Draft 2019-09 for deprecated support $schema = Schema::fromClass( ModernUser::class, - version: SchemaVersion::Draft_2019_09 + schemaVersion: SchemaVersion::Draft_2019_09 ); // The generated schema will include "deprecated": true for old_email diff --git a/docs/json-schema/code-generation/from-closures.mdx b/docs/json-schema/code-generation/from-closures.mdx index 3614e05..86ccf30 100644 --- a/docs/json-schema/code-generation/from-closures.mdx +++ b/docs/json-schema/code-generation/from-closures.mdx @@ -319,7 +319,7 @@ $modernApiClosure = function ( // Generate with Draft 2019-09 for deprecated support $modernSchema = Schema::fromClosure( $modernApiClosure, - version: SchemaVersion::Draft_2019_09 + schemaVersion: SchemaVersion::Draft_2019_09 ); // Apply validation rules programmatically after generation diff --git a/docs/json-schema/code-generation/from-enums.mdx b/docs/json-schema/code-generation/from-enums.mdx index 2c22a8a..4577dae 100644 --- a/docs/json-schema/code-generation/from-enums.mdx +++ b/docs/json-schema/code-generation/from-enums.mdx @@ -151,7 +151,7 @@ enum OrderStatus: string // Generate with Draft 2019-09 for advanced features $schema = Schema::fromEnum( OrderStatus::class, - version: SchemaVersion::Draft_2019_09 + schemaVersion: SchemaVersion::Draft_2019_09 ); // The generated schema includes all enum values in the enum array diff --git a/docs/json-schema/schema-types/union.mdx b/docs/json-schema/schema-types/union.mdx index a7dfd2a..f30c644 100644 --- a/docs/json-schema/schema-types/union.mdx +++ b/docs/json-schema/schema-types/union.mdx @@ -246,9 +246,9 @@ $dbFieldSchema = Schema::union([ $recordSchema = Schema::object('database_record') ->properties( - Schema::integer('id')->required(), - Schema::additionalProperties($dbFieldSchema) + Schema::integer('id')->required() ) + ->additionalProperties($dbFieldSchema) ->description('Flexible database record with typed fields'); ``` diff --git a/docs/json-schema/validation/error-handling.mdx b/docs/json-schema/validation/error-handling.mdx index de37f01..864048f 100644 --- a/docs/json-schema/validation/error-handling.mdx +++ b/docs/json-schema/validation/error-handling.mdx @@ -25,8 +25,10 @@ try { } 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) + + // Get detailed error information + $errors = $e->getErrors(); + print_r($errors); // Array with paths as keys and messages as values } ``` @@ -75,7 +77,13 @@ foreach ($testCases as $index => $testData) { } catch (SchemaException $e) { echo "Test case {$index}: {$e->getMessage()}\n"; echo " Error code: {$e->getCode()}\n"; - echo " Failed property: " . ($e->getProperty() ?? 'unknown') . "\n\n"; + + // Get detailed errors with property paths + $errors = $e->getErrors(); + foreach ($errors as $path => $message) { + echo " Failed property: {$path} - {$message}\n"; + } + echo "\n"; } } ``` @@ -141,8 +149,12 @@ $requiredSchema = Schema::object('user') try { $requiredSchema->validate(['name' => 'John']); // Missing email } catch (SchemaException $e) { - echo $e->getMessage(); // "Property 'email' is required" - echo $e->getProperty(); // "email" + echo $e->getMessage(); // Error message + + // Get detailed errors + $errors = $e->getErrors(); + // Errors array contains property paths as keys + print_r($errors); } ``` @@ -190,10 +202,14 @@ class UserFriendlyErrorHandler public function getFieldSpecificMessage(SchemaException $e): string { - $property = $e->getProperty(); + $errors = $e->getErrors(); $friendlyMessage = $this->getFriendlyMessage($e); - - if ($property) { + + // Get the first error property path + if (!empty($errors)) { + $firstPath = array_key_first($errors); + // Remove leading slash and convert to readable format + $property = ltrim($firstPath, '/'); $fieldName = ucfirst(str_replace('_', ' ', $property)); return "{$fieldName}: {$friendlyMessage}"; } @@ -261,7 +277,6 @@ class ValidatorWithResults 'message' => $e->getMessage(), 'code' => $e->getCode(), 'field' => $e->getProperty(), - 'value' => $e->getFailedValue() ]; } @@ -320,7 +335,6 @@ class NestedErrorHandler $errors[] = [ 'path' => $fieldPath, 'message' => $e->getMessage(), - 'value' => $e->getFailedValue() ]; } @@ -427,11 +441,14 @@ Provide helpful suggestions for common validation errors: ```php class ErrorRecoveryHelper { - public function suggestCorrections(SchemaException $e): array + /** + * Suggest corrections based on validation errors. + * Note: Pass the original value if you need value-specific suggestions. + */ + public function suggestCorrections(SchemaException $e, mixed $value = null): array { $suggestions = []; $message = $e->getMessage(); - $value = $e->getFailedValue(); // Email format suggestions if (strpos($message, 'email') !== false && is_string($value)) { @@ -480,14 +497,13 @@ class ErrorRecoveryHelper return $suggestions; } - public function getDetailedError(SchemaException $e): array + public function getDetailedError(SchemaException $e, mixed $value = null): array { return [ 'message' => $e->getMessage(), 'code' => $e->getCode(), 'field' => $e->getProperty(), - 'value' => $e->getFailedValue(), - 'suggestions' => $this->suggestCorrections($e) + 'suggestions' => $this->suggestCorrections($e, $value) ]; } } diff --git a/src/Exceptions/SchemaException.php b/src/Exceptions/SchemaException.php index 56a7513..fc4c24d 100644 --- a/src/Exceptions/SchemaException.php +++ b/src/Exceptions/SchemaException.php @@ -45,4 +45,41 @@ public function getErrors(): array return $errors; } + + /** + * Get the first property path that failed validation. + * Returns the property path without the leading slash (e.g., 'email' instead of '/email'). + * + * @return string|null The property path or null if no errors + */ + public function getProperty(): ?string + { + $errors = $this->getErrors(); + + if (empty($errors)) { + return null; + } + + $firstPath = array_key_first($errors); + + // Remove leading slash for cleaner output + return ltrim((string) $firstPath, '/'); + } + + /** + * Get the first property path that failed validation with the leading slash. + * Returns the full path as used in the errors array (e.g., '/email'). + * + * @return string|null The full property path or null if no errors + */ + public function getPropertyPath(): ?string + { + $errors = $this->getErrors(); + + if (empty($errors)) { + return null; + } + + return (string) array_key_first($errors); + } }