Download the PHP package vanilla/garden-schema without Composer

On this page you can find all versions of the php package vanilla/garden-schema. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package garden-schema

Garden Schema

Packagist Version MIT License CLA

The Garden Schema is a simple data validation and cleaning library based on OpenAPI 3.0 Schema.

Features

Uses

Garden Schema is meant to be a generic wrapper for data validation. It should be valuable when you want to bullet-proof your code against user-submitted data. Here are some example uses:

Basic Usage

To validate data you first create an instance of the Schema class and then call its validate() method.

In the above example a Schema object is created with the schema definition passed to its constructor (more on that later). Data to be validated can then be passed to the validate() method. If the data is okay then a clean version is returned, otherwise a ValidationException is thrown.

Defining Schemas

The Schema class is instantiated with an array defining the schema. The array can be in OpenAPI 3.0 Schema format or it can be in custom short format. It is recommended you define your schemas in the OpenAPI format, but the short format is good for those wanting to write quick prototypes. The short format will be described in this section.

By default the schema is an array where each element of the array defines an object property. By "object" we mean javascript object or PHP array with string keys. There are several ways a property can be defined:

You can quickly define an object schema by giving just as much information as you need. You can create a schema that is nested as deeply as you want in order to validate very complex data. This short schema is converted into a JSON schema compatible array internally and you can see this array with the jsonSerialize() method.

We provide first-class support for descriptions because we believe in writing readable code right off the bat. If you don't like this you can just leave the descriptions out and they will be left empty in the schema.

Types and Short Types

The Schema class supports the following types. Each type has one or more aliases. You can use an alias for brevity when defining a schema in code and it gets converted to the proper type internally, including when used in errors.

Type Aliases Notes
boolean b, bool
string s, str, dt The "dt" alias adds a format of "date-time" and validates to DateTimeInterface instances
integer i, int, ts The "ts" alias adds a format of "timestamp" and will convert date strings into integer timestamps on validation.
number f, float
array a
object o

Arrays and Objects

The array and object types are a bit special as they contain several elements rather than a single value. Because of this you can define the type of data that should be in those properties. Here are some examples:

Re-usable schemas

Schemas can be nested and composed.

Enum Values

You use a PHP \BackedEnum for validation.

Entity Classes

Entity classes allow you to define strongly-typed data objects that automatically generate schemas from their properties using reflection. Validated data is cast into entity instances.

Defining an Entity

Create a class extending Garden\Schema\Entity with public properties:

Using Entities

Use Entity::getSchema() to get the generated schema, or Entity::from() to validate and create an instance:

If you pass an existing entity instance to from(), it returns that instance without re-validating:

Note: When an existing entity is passed, it is assumed to already be valid. If you've manually modified properties to invalid values, those won't be caught. Use Entity::from($entity->toArray()) if you need to re-validate a modified entity.

Property Type Mapping

Entity properties are mapped to schema types as follows:

PHP Type Schema Type
string string
int integer
float number
bool boolean
array array
ArrayObject object
DateTimeImmutable string with format: date-time
UuidInterface string with format: uuid
BackedEnum subclass string or integer with enumClassName
Entity subclass Nested object schema with entityClassName
Untyped No type validation (accepts any value)

Properties with nullable types (?string) or default values are optional. All other typed properties are required.

The PropertySchema Attribute

Use #[PropertySchema] to customize property schemas. The provided schema array is merged with the auto-generated schema from the property's type, allowing you to add constraints while preserving type inference:

Helper Attributes

Garden Schema provides several helper attributes that extend PropertySchema for common constraints:

Attribute Description
#[Required] Marks a nullable property as required (must be explicitly provided)
#[MinLength(n)] Sets minimum string length
#[MaxLength(n)] Sets maximum string length
#[MinItems(n)] Sets minimum array item count
The Required Attribute

Use #[Required] to mark a nullable property as required. This is useful when you have a property that accepts null as a valid value, but must always be explicitly provided:

The PropertyAltNames Attribute

Use #[PropertyAltNames] to specify alternative property names that map to a property. This is useful for handling legacy field names, API versioning, or data from different sources:

When multiple alt names are provided, you must specify the primaryAltName parameter. This determines which alt name is used when serializing back via toArray(form: EntityFieldFormat::PrimaryAltName).

Dot Notation for Nested Values

When useDotNotation is enabled (the default), alt names containing dots are treated as nested paths:

Serializing Back to Alt Names

Use toArray(form: EntityFieldFormat::PrimaryAltName) to serialize an entity back using the alternative property names. This is useful when you need to round-trip data that was originally in an alternative format:

Using EntityFieldFormat::PrimaryAltName also reverses MapSubProperties mappings, extracting nested values back to their original locations:

Converting Field Names Programmatically

Use convertFieldName() and convertFieldNames() to convert between canonical property names and their primary alt names without creating or serializing an entity. These methods use a statically cached field name map built from PropertyAltNames attributes, so they are efficient for repeated use.

The EntityFieldFormat enum specifies the target format:

Dot-notation alt names are also supported:

This is useful for translating field names in contexts such as database queries, sorting parameters, or API filters where you need to map between internal property names and external field names without full entity hydration.

The MapSubProperties Attribute

Use #[MapSubProperties] to construct nested entity or ArrayObject properties from data scattered across the input. This is useful when your input data has a flat structure but your entity has nested objects:

The attribute has two parameters:

Key behaviors:

  1. Values are copied, not moved: The original data remains in place; values are copied into the nested structure.

  2. Missing paths are silently skipped: If a source path doesn't exist, that mapping is simply skipped without error.

  3. Additive behavior: If the target property already has data, new values are merged in rather than replacing the entire structure.

  4. Applied before validation: The mapping happens as a filter before schema validation, so the constructed nested object is then validated against its schema.

The ExcludeFromSchema Attribute

Use #[ExcludeFromSchema] to exclude a property from schema generation and validation. This is useful for computed properties, caches, or internal state that shouldn't be part of the data model:

Schema Variants

Entities support multiple schema variants for different API use cases. This allows a single Entity class to generate different schemas depending on the context:

Variant Use Case
Full Complete entity with all properties (default). Used for single-item GET responses.
Fragment Reduced version for lists. Omits large strings and detail fields.
Mutable Fields that can be modified by consumers. Used for PATCH requests.
Create Includes create-only fields. Used for POST requests.
Internal For system/internal use. May include sensitive fields not exposed via API.

Use Entity::getSchema() with a SchemaVariant parameter to get different variants:

By default, all properties are included in all variants. Use attributes to customize which properties appear in each variant.

The ExcludeFromVariant Attribute

Use #[ExcludeFromVariant] to exclude a property from specific schema variants:

The attribute is repeatable, so you can also use multiple attributes:

The IncludeOnlyInVariant Attribute

Use #[IncludeOnlyInVariant] to include a property only in specific variants. Properties with this attribute are excluded from all other variants (including Full unless specified):

Note: If both #[IncludeOnlyInVariant] and #[ExcludeFromVariant] are present on the same property, #[IncludeOnlyInVariant] takes precedence.

Schema Variant Caching

Each schema variant is cached separately using the EntitySchemaCache utility class. You can invalidate caches at different levels:

Using EntitySchemaCache Directly

The EntitySchemaCache class provides low-level cache management and can be used directly for advanced scenarios:

The cache automatically detects circular references during schema building and throws a RuntimeException if detected.

Custom Variant Enums

You can define your own variant enums instead of using SchemaVariant. This is useful when you need domain-specific variants:

Custom variants are cached separately and can be mixed with SchemaVariant on the same entity.

Serialization Variants

You can control which properties are included when converting an entity to an array or JSON by using serialization variants:

The serialization variant is propagated to nested entities during serialization:

The NestedVariant Attribute

By default, when serializing an entity, nested entities inherit the same variant as their parent. Use #[NestedVariant] to specify a different variant for a specific nested entity property:

This is useful for:

The #[NestedVariant] attribute also affects schema generation. When generating the parent's schema, the nested entity's schema will use the specified variant:

Arrays of entities also respect #[NestedVariant]:

Nested Entities

Entities can reference other entities. Nested data is automatically validated and cast:

Default Values for Nested Entities

PHP doesn't allow default values for properties that require class instantiation. To provide default values for nested entity properties, implement the EntityDefaultInterface:

When a property's type implements EntityDefaultInterface:

  1. Schema includes the default: The generated schema will have a default key with the serialized default values, useful for OpenAPI documentation.
  2. Hydration uses the default: When from() or fromValidated() is called without that property, the default instance is used.
  3. Property is not required: The property is automatically treated as optional in the schema.

Distinguishing absent values from explicit null:

For nullable properties, there's a distinction between not providing a value (uses default) and explicitly setting null:

The generated schema includes the default:

ArrayObject Properties

Properties typed as ArrayObject (or subclasses) are mapped to object in the schema. Arrays are automatically converted to ArrayObject instances during validation:

ArrayObject instances are preserved in toArray() and JSON serialization to ensure empty objects serialize as {} (JSON object) rather than [] (JSON array):

DateTimeImmutable Properties

Properties typed as DateTimeImmutable are mapped to string with format: date-time in the schema. Date-time strings are automatically converted to DateTimeImmutable instances, and serialized to RFC3339 format (or RFC3339_EXTENDED if milliseconds are present):

UuidInterface Properties

Properties typed as Ramsey\Uuid\UuidInterface are mapped to string with format: uuid in the schema. UUID strings are automatically validated and converted to UuidInterface instances. Binary 16-byte UUIDs are also supported:

You can also use UUID format in schema definitions:

Using entityClassName in Schemas

You can reference entity classes directly in schema definitions, similar to BackedEnum:

Converting to Arrays and JSON

Entities implement ArrayAccess and JsonSerializable:

Note: Writing via ArrayAccess (e.g., $user['age'] = 'not a number') and direct property assignment do NOT perform validation. Use Entity::from() for validated construction, or call $entity->validate() after modifications to verify the entity is valid.

Validating After Modifications

After modifying an entity directly, you can call validate() to verify it's still in a valid state:

Partial Updates with update()

Use update() to apply partial, validated updates to an existing entity. It validates the input against the Mutable schema variant (sparse), maps field names from alt names and sub-property mappings (just like from()), sets the properties on the entity, tracks which fields were updated, and validates the full entity state:

Alt names and MapSubProperties mappings work the same as in from():

If the update data is invalid or the resulting entity state is invalid, a ValidationException is thrown.

Retrieving Updated Fields with getUpdatedArray()

After calling update(), use getUpdatedArray() to get only the fields that were modified. This is useful for building database UPDATE statements or audit logs:

Multiple update() calls accumulate tracked fields:

The EntityInterface and EntityTrait

If you have a class that already extends another class and cannot extend Entity, you can implement the EntityInterface directly. To reduce boilerplate, use the EntityTrait which provides default implementations for from(), validate(), setSerializationVariant(), and getSerializationVariant().

With EntityTrait, you only need to implement three methods:

The EntityTrait provides these methods automatically:

Classes implementing EntityInterface can be used anywhere an entity is expected:

Note: The abstract Entity class provides a complete implementation with reflection-based schema generation, caching via EntitySchemaCache, ArrayAccess, and JsonSerializable. For most use cases, extending Entity is recommended. The Entity class itself uses EntityTrait internally.

Non-Object Schemas

By default, schemas define an object because that is the most common use for a schema. If you want a schema to represent an array or even a basic type you define a single field with no name. The following example defines an array of objects (i.e. the output of a database query).

This schema would apply to something like the following data:

Optional Properties and Nullable Properties

When defining an object schema you can use a "?" to say that the property is optional. This means that the property can be completely omitted during validation. This is not the same a providing a null value for the property which is considered invalid for optional properties.

If you want a property to allow null values you can specify the nullable attribute on the property. There are two ways to do this:

Default Values

You can specify a default value with the default attribute. If the value is omitted during validation then the default value will be used. Note that default values are not applied during sparse validation.

Validating Data

Once you have a schema you validate data using the validate() or isValid() methods.

The Schema::validate() method

You pass the data you want to validate to Schema::validate() and it it either returns a cleaned copy of your data or throws a ValidationException.

Calling validate() on user-submitted data allows you to check your data early and bail out if it isn't correct. If you just want to check your data without throwing an exception the isValid() method is a convenience method that returns true or false depending on whether or not the data is valid.

The ValidationException and Validation Classes

When you call validate() and validation fails a ValidationException is thrown. This exception contains a property that is a Validation object which contains more information about the fields that have failed.

If you are writing an API, you can json_encode() the ValidationException and it should provide a rich set of data that will help any consumer figure out exactly what they did wrong. You can also use various properties of the Validation property to help render the error output appropriately.

The Validation JSON Format

The Validation object and ValidationException both encode to a specific format. Here is an example:

This format is optimized for helping present errors to user interfaces. You can loop through the specific errors collection and line up errors with their inputs on a user interface. For deeply nested objects, the field name is a JSON reference.

Schema References

OpenAPI allows for schemas to be accessed with references using the $ref attribute. Using references allows you to define commonly used schemas in one place and then reference them from many locations.

To use references you must:

  1. Define the schema you want to reference somewhere.
  2. Reference the schema with a $ref attribute.
  3. Add a schema lookup function to your main schema with Schema::setRefLookp()

Defining a Reusable Schema

The OpenAPI specification places all reusable schemas under /components/schemas. If you are defining everything in a big array that is a good place to put them.

Referencing Schemas With $ref

Reference the schema's path with keys separated by / characters.

Using Schema::setRefLookup() to Resolve References

The Schema class has a setRefLookup() method that lets you add a callable that is use to resolve references. The callable should have the following signature:

The function takes the string from the $ref attribute and returns a schema array, Schema object, or null if the schema cannot be found. Garden Schema has a default implementation of a ref lookup in the ArrayRefLookup class that can resolve references from a static array. This should be good enough for most uses, but you are always free to define your own.

You can put everything together like this:

The references are resolved during validation so if there are any mistakes in your references then a RefNotFoundException is thrown during validation, not when you set your schema or ref lookup function.

Schema Polymorphism

Schemas have some support for implementing schema polymorphism by letting you validate an object against different schemas depending on its value.

The discriminator Property

The discriminator of a schema lets you specify an object property that specifies what type of object it is. That property is then used to reference a specific schema for the object. The discriminator has the following format:

You can see above that the propertyName specifies which property is used as the discriminator. There is also an optional mapping property that lets you control how schemas are mapped to values. discriminators are resolved int he following way:

  1. The property value is mapped using the mapping property.
  2. If the value is a valid JSON reference then it is looked up. Only values in mappings can specify a JSON reference in this way.
  3. If the value is not a valid JSON reference then it is is prepended with #/components/schemas/ to make a JSON reference.

Here is an example at work:

The oneOf Property

The oneOf property works in conjunction with the discriminator to limit the schemas that the object is allowed to validate against. If you don't specify oneOf then any schemas under #/components/schemas are fair game.

To use the oneOf property you must specify $ref nodes like so:

In the above example the "species" property will be used to construct a reference to a schema. That reference must match one of the references in the oneOf property.

If you are familiar with with OpenAPI spec please note that inline schemas are not currently supported for oneOf in Garden Schema.

Validation Options

Both validate() and isValid() can take an additional $options argument which modifies the behavior of the validation slightly, depending on the option.

The request Option

You can pass an option of ['request' => true] to specify that you are validating request data. When validating request data, properties that have been marked as readOnly: true will be treated as if they don't exist, even if they are marked as required.

The response Option

You can pass an option of ['response' => true] to specify that you are validating response data. When validating response data, properties that have been marked as writeOnly: true will be treated as if they don't exist, even if they are marked as required.

The sparse Option

You can pass an option of ['sparse' => true] to specify a sparse validation. When you do a sparse validation, missing properties do not give errors and the sparse data is returned. Sparse validation allows you to use the same schema for inserting vs. updating records. This is common in databases or APIs with POST vs. PATCH requests.

Flags

Flags can be applied a schema to change it's inherit validation.

VALIDATE_STRING_LENGTH_AS_UNICODE

By default, schema's validate str lengths in terms of bytes. This is useful because this is the common unit of storage for things like databases.

Some unicode characters take more than 1 byte. An emoji like 😱 takes 4 bytes for example.

Enable this flag to validate unicode character length instead of byte length.

VALIDATE_EXTRA_PROPERTY_NOTICE

Set this flag to trigger notices whenever a validated object has properties not defined in the schema.

VALIDATE_EXTRA_PROPERTY_EXCEPTION

Set this flag to throw an exception whenever a validated object has properties not defined in the schema.

Custom Validation with addValidator()

You can customize validation with Schema::addValidator(). This method lets you attach a callback to a schema path. The callback has the following form:

The callback should true if the value is valid or false otherwise. You can use the provided ValidationField to add custom error messages.

Filtering Data

You can filter data before it is validating using Schema::addFilter(). This method lets you filter data at a schema path. The callback has the following form:

The callback should return the filtered value. Filters are called before validation occurs so you can use them to clean up date you know may need some extra processing.

The Schema::addFilter() also accepts $validate parameter that allows your filter to validate the data and bypass default validation. If you are validating date in this way you can add custom errors to the ValidationField parameter and return Invalid::value() your validation fails.

Format Filters

You can also filter all fields with a particular format using the Schema::addFormatFilter(). This method works similar to Schema::addFilter() but it applies to all fields that match the given format. You can even use format filters to override default format processing.

Overriding the Validation Class and Localization

Since schemas generate error messages, localization may be an issue. Although the Garden Schema doesn't offer any localization capabilities itself, it is designed to be extended in order to add localization yourself. You do this by subclassing the Validation class and overriding its translate() method. Here is a basic example:

There are a few things to note in the above example:

JSON Schema Support

The Schema object is a wrapper for an OpenAPI Schema array. This means that you can pass a valid JSON schema to Schema's constructor. The table below lists the JSON Schema properties that are supported.

Property Applies To Notes
allOf Schema[] An instance validates successfully against this keyword if it validates successfully against all schemas defined by this keyword's value.
multipleOf integer/number A numeric instance is only valid if division by this keyword's value results in an integer.
maximum integer/number If the instance is a number, then this keyword validates only if the instance is less than or exactly equal to "maximum".
exclusiveMaximum integer/number If the instance is a number, then the instance is valid only if it has a value strictly less than (not equal to) "exclusiveMaximum".
minimum integer/number If the instance is a number, then this keyword validates only if the instance is greater than or exactly equal to "minimum".
exclusiveMinimum integer/number If the instance is a number, then the instance is valid only if it has a value strictly greater than (not equal to) "exclusiveMinimum".
maxLength string Limit the unicode character length of a string.
minLength string Minimum length of a string.
maxByteLength string Maximum byte length of the the property.
pattern string A regular expression without delimiters. You can add a custom error message with the x-patternMessageCode field.
items array Ony supports a single schema.
maxItems array Limit the number of items in an array.
minItems array Minimum number of items in an array.
uniqueItems array All items must be unique.
maxProperties object Limit the number of properties on an object.
minProperties object Minimum number of properties on an object.
additionalProperties object Validate additional properties against a schema. Can also be true to always validate.
required object Names of required object properties.
properties object Specify schemas for object properties.
enum any Specify an array of valid values.
type any Specify a type of an array of types to validate a value.
default object Applies to a schema that is in an object property.
format string Support for date-time, email, ipv4, ipv6, ip, uri, uuid.
oneOf object Works with the discriminator property to validate against a dynamic schema.

OpenAPI Schema Support

OpenAPI defines some extended properties that are applied during validation.

Property Type Notes
nullable boolean If a field is nullable then it can also take the value null.
readOnly boolean Relevant only for Schema "properties" definitions. Declares the property as "read only". This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. If the property is marked as readOnly being true and is in the required list, the required will take effect on the response only.
writeOnly boolean Relevant only for Schema "properties" definitions. Declares the property as "write only". Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. If the property is marked as writeOnly being true and is in the required list, the required will take effect on the request only.
discriminator object Validate against a dynamic schema based on a property value.

All versions of garden-schema with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
ramsey/uuid Version ^4.9
vanilla/garden-utils Version ^1.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package vanilla/garden-schema contains the following files

Loading the files please wait ...