The Zec Data Parsing and schema declaration Library is designed to bring schema definition and validation capabilities to PHP applications.
composer require mohamed-amine-sayagh/zec
Here's an example of how to use the Zec library to define and validate a user profile schema:
use function ZecUtilsz;
// Define the user profile schema
$userProfileParser = z()->options([
'name' => z()->string()->min(3)->max(50), // Name must be a string between 3 and 50 characters
'age' => z()->number()->min(18), // Age must be a number and at least 18
'email' => z()->email(), // Email must be a valid email address
'address' => z()->options([
'street' => z()->string(),
'city' => z()->string()
]),
'hobbies' => z()->each(z()->string()), // Hobbies must be an array of strings
'metadata' => z()->optional()->each(z()->options([ // Metadata is optional and must be an array of objects
'key' => z()->string(), // Each object must have a key as a string
'value' => z()->string() // Each object must have a value as a string
]))
]);
// Parse and validate user data
$userData = [
'name' => 'Jane Doe',
'age' => 1, // 1 is not a valid age
'email' => 'jane.doe@examplecom', // missing dot
'address' => [
'street' => '123 Elm St',
'city' => 3 // city is not a string
],
'hobbies' => ['photography', 'traveling', 'reading', 5], // 5 is not a string
'metadata' => [
['key' => 'memberSince', 'value' => '2019'],
['key' => 'newsletter', 'value' => 'true']
]
];
try {
$userProfileParser->parseOrThrow($userData); // Throws an error
echo "User data is validn";
} catch (ZecZecError $e) {
echo "User data is invalid: ";
$e->log(); // Log the error
}
User data is invalid: [
{
"parser": "min",
"value": 1,
"min": 18,
"message": "Invalid value",
"path": [
"age"
]
},
{
"parser": "email",
"value": "jane.doe@examplecom",
"message": "Invalid email address",
"path": [
"email"
]
},
{
"parser": "string",
"value": 5,
"message": "Invalid string value",
"path": [
"hobbies",
"3"
]
}
]
Current Version: v1.0.0, Release Date: 2024-10-01, Author: Mohamed Amine SAYAGH, Release Notes: Initial release of the Zec PHP Data Parsing Library., Release Link: [Zec 1.0.0](
Note: This library is currently in development. Official documentation and further resources will be available soon.
Author Information:
We are fully open to collaboration! If you're interested in contributing to the PHP Data Parsing Library, we'd love to hear from you. Whether it's through code contributions, documentation improvements, or feature suggestions, your input is highly welcome.
For more details, check our contribution guidelines (link to detailed contribution guidelines if available).
We look forward to building a powerful data parsing tool with a vibrant community of contributors!
Define and validate data types using simple schema definitions:
use function ZecUtilsz;
$my_schema = z()->string();
$response_valid = $my_schema->parse("Hello, World!"); // Returns Zec data object
$value = $response_valid->value; // Returns "Hello, World!"
$response_invalid = $my_schema->parse(123); // Returns Zec data object
$errors = $response_invalid->errors; // Returns an array of ZecError object an exception extends class
Quickly validate data after parsing:
$is_valid = $my_schema->parse("Hello, World!")->isValid(); // Returns true
$is_invalid = $my_schema->parse(123)->isValid(); // Returns false
Handle exceptions using parse_or_throw for critical data validation:
try {
$response = $my_schema->parseOrThrow(123); // Throws ZecError
} catch (ZecError $error) {
$error_message = $error->message; // Returns "Invalid type: expected string, received integer"
$error->log(); // Logs the error
}
You can enhance the schema definition by incorporating additional validation options. This allows for more detailed control over data conformity based on specific requirements.
use function Zecz;
$user_schema = z()->options([
'name' => z()->string()->min(3)->max(50),
'email' => z()->email(),
'age' => z()->number()->min(18),
'isActive' => z()->boolean(),
'registrationDate' => z()->date()
]);
// Parsing a valid user object
$valid_user = $user_schema->parse([
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 30,
'isActive' => true,
'registrationDate' => '2021-01-01'
]);
// Parsing an invalid user object
$invalid_user = $user_schema->parse([
'name' => 'JD', // Too short
'email' => 'john.doe@', // Invalid email format
'age' => 17, // Below minimum age requirement
'isActive' => 'yes', // Incorrect type (should be boolean)
'registrationDate' => '01-01-2021' // Wrong date format
]);
// Handling validation results
if ($valid_user->isValid()) {
echo 'User is valid.';
} else {
echo 'User is invalid. Errors: ';
var_dump($valid_user->errors());
}
if ($invalid_user->isValid()) {
echo 'User is valid.';
} else {
echo 'User is invalid. Errors: ';
var_dump($invalid_user->errors());
}
The library provides extensive Configurability for data validation, allowing users to define complex validation rules with custom messages and conditions. Below is an example of how to configure a detailed schema for an email field with specific validation rules:
use function Zecz;
// Define a configurable email schema
$my_configurable_email_schema = z()->string([
'message' => 'Invalid string data'
])->min([
'min' => 3,
'message' => 'String data must be at least 3 characters long' // Custom message
])->max([
'max' => 10,
'message' => 'String {{value}} must be at most ((max)) characters long' // Custom message with value interpolation
]).email([
'message' => 'Invalid email',
'domain' => ['gmail.com', 'yahoo.com'] // Custom domain validation rules
]);
// Define a user schema using the configurable email schema
$my_user = z()->options([
'email' => $my_configurable_email_schema->required()
]);
This example demonstrates validating a user data structure that includes nested arrays, optional fields, and union types, showcasing the library's capability to handle complex and realistic data models.
use function Zecz;
// Define a user schema with various data validation rules
$user_parser = z()->options([
'name' => z()->required()->string()->min(3)->max(50),
'email' => z()->url([
'message' => 'Invalid email address',
'domain' => ['gmail.com']
]),
'age' => z()->number(),
'friends' => z()->each(
function ($user) {
return $user->nullable();
} // Each friend is a user object (nullable)
),
'password' => z()->optional()->options([
'password' => z()->string(), // Path: 'password.password'
'confirm_password' => z()->string(),
'created_at' => z()->date(),
]),
'created_at' => z()->date(),
'updated_at' => z()->date(),
'document' => z()->union([
z()->options([
'type' => z()->enum(['student']),
'content' => z()->options([
'school' => z()->string(),
'grade' => z()->number(),
]),
]),
z()->options([
'type' => z()->enum(['teacher']),
'content' => z()->options([
'school' => z()->string(),
'subject' => z()->string(),
]),
]),
]) // Union type for document, can be student or teacher document
]);
// Parse a valid user object
$user = $user_parser->parse([
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 25,
'friends' => [
[
'name' => 'Jane Doe',
'email' => '[email protected]',
'age' => 30,
],
],
'password' => [
'password' => 'password',
'confirm_password' => 'password',
'created_at' => '2021-10-10'
],
'created_at' => '2021-10-10',
'updated_at' => '2021-10-10',
'document' => [
'type' => 'student',
'content' => [
'school' => 'School',
'grade' => 10,
]
]
]); // Returns a Zec object
// Validate the parsed data
if ($user->isValid()) {
echo 'User is valid.';
var_dump($user->getValue()); // Outputs the validated data
} else {
echo 'User is invalid.';
var_dump($user->errors()); // Outputs validation errors
}
To enhance flexibility and cater to specific validation needs, our library allows users to define custom parser methods. This section demonstrates how to create a size
parser method, which validates that the size of an array, length of a string, or value of a number meets a specific requirement.
The size
method checks if:
Here is how you can implement this custom parser:
use function Zecz;
use function Zecbundler;
use ZecFIELD as FK;
$custom_size_parser = parser_build()
->name('size')
->prioritize('string', 'number', 'array') // Prioritize the parser for string, number, and array types
->argument('message', 'Invalid size', function (ZecZec $z) {
return $z->required()->string();
}) // argument for custom message, default is 'Invalid size'
->argument('size', 0, function (ZecZec $z) {
return $z->required()->number();
}) // argument for size, default is 0
->function(function (array $args): string|bool {
$value = $args['value'];
$expected_size = $args['size'];
$message = $args['message'];
if (is_array($value)) {
$actual_size = count($value);
} elseif (is_string($value)) {
$actual_size = strlen($value);
} elseif (is_numeric($value)) {
$actual_size = $value;
} else {
return $message ?? 'Invalid data type';
}
if ($actual_size === $expected_size) {
return true;
}
return $message ?? 'Invalid size';
})->priority(4); // priority of the parser, the default priority of parser is 10, parser with 5 as priority will override before parser with 10 as priority if they have the same parser name
->build(); // Build the parser
bundler->addParser($custom_size_parser);
You can now use the custom size
parser method in your schema definitions:
$my_schema = z()->options([
'username' => z()->string()->size(5), // Username must be a string of length 5
'favorite_numbers' => z()->array()->size(5), // Favorite numbers must be an array of length 5
'lucky_number' => z()->number()->size(5), // Lucky number must be 5
]);
$user_data = [
'username' => 'admin',
'favorite_numbers' => [1, 2, 3, 4, 5],
'lucky_number' => 5
]; // Valid data
$parsed_data = $my_schema->parse($user_data); // Returns a Zec object
// Validate the parsed data
if ($parsed_data->isValid()) { // Returns true if data is valid
echo 'All data is valid.';
} else {
echo 'Data validation failed. Errors: ';
var_dump($parsed_data->errors()); // Outputs validation errors
}
This project is licensed under the MIT License - see the LICENSE.md file for details.
Copyright (c) 2024 Mohamed Amine SAYAGH
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.