Oihana PHP System

AlterDocumentTrait uses trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short, trait:short

Provides a system to alter properties of arrays or objects based on a configurable set of rules (called "alters").

The alteration definitions are stored in the $alters array and can apply various transformations to data, such as converting values to floats, parsing JSON, cleaning arrays, or resolving URLs.

Now supports chaining multiple alterations on a single property:

Example usage:

class MyProcessor
{
    use AlterDocumentTrait;

    public function __construct()
    {
        $this->alters =
        [
            'price' => Alter::FLOAT,
            'tags'  => [ Alter::ARRAY , Alter::CLEAN ],
            'meta'  => [ Alter::JSON_PARSE ],
            'link'  => [ Alter::URL , '/product/' ],
            'score' => [ Alter::CALL , fn($value) => $value * 10 ],
            'geo'   => [ Alter::NORMALIZE , [ Alter::HYDRATE , GeoCoordinates::class ] ],
            'name'  => [ Alter::TRIM , Alter::UPPERCASE , Alter::NORMALIZE ],
        ];
    }
}

Supported alteration types (see enum Alter):

  • Alter::ARRAY → Split string into array and apply sub-alters.
  • Alter::CLEAN → Remove empty/null elements from an array.
  • Alter::CALL → Call a function on the value.
  • Alter::FLOAT → Convert to float (or array of floats).
  • Alter::GET → Fetch a document using a model.
  • Alter::HYDRATE → Hydrate a value with a specific class.
  • Alter::INT → Convert to integer (or array of integers).
  • Alter::JSON_PARSE → Parse JSON string.
  • Alter::JSON_STRINGIFY → Convert value to JSON string.
  • Alter::NORMALIZE → Normalize a document property using configurable flags.
  • Alter::NOT → Invert boolean values.
  • Alter::URL → Generate a URL from a property.
  • Alter::VALUE → Override with a fixed value.
Tags
throws
ContainerExceptionInterface
throws
NotFoundExceptionInterface
throws
DependencyException
throws
NotFoundException
author

Marc Alcaraz (ekameleon)

since
1.0.0

Table of Contents

Properties

$alterKey  : string
The default alter key reference.
$alters  : array<string|int, mixed>
The enumeration of all definitions to alter on the array or object key/value properties.
$container  : Container
The DI container reference.

Methods

alter()  : mixed
Alters the given document (array or object) based on the configured `$alters` definitions.
alterArrayCleanProperty()  : array<string|int, mixed>|float
Clean an array of null or empty string elements.
alterArrayElements()  : array<string|int, mixed>
Alters all elements in an array.
alterArrayProperty()  : array<string|int, mixed>
Transform a string expression separated by semi-colon ';' to creates an array.
alterCallableProperty()  : mixed
Call a function to alter a property.
alterFloatProperty()  : array<string|int, mixed>|float
Cast a value to float. If the value is an array, all elements in the array are casted.
alterGetDocument()  : mixed
Gets a document with a Documents model.
alterHydrateProperty()  : mixed
Hydrate a property value into a specific class instance using reflection.
alterIntProperty()  : array<string|int, mixed>|int
Cast a value to integer.
alterJsonParseProperty()  : string|false|null
Decodes a JSON string
alterJsonStringifyProperty()  : string|false|null
Returns the JSON representation of a value
alterNormalizeProperty()  : mixed
Normalize a document property using configurable flags.
alterNotProperty()  : bool|array<string|int, mixed>
Invert a boolean value or an array of booleans.
alterUrlProperty()  : string
Generates a complete URL by combining path segments and document properties.
alterValue()  : mixed
Replace a value with a new one if different, otherwise keep the original.
initializeAlterKey()  : static
Initialize the 'alters' property.
initializeAlters()  : static
Initialize the 'alters' property.
alterProperty()  : array<string|int, mixed>|object
Alters a specific property of the given document using one or more transformation rules.
applyChainedAlterations()  : array<string|int, mixed>|object
Applies chained alterations to a property.
applySingleAlteration()  : array<string|int, mixed>|object
Applies a single alteration (original behavior).
executeAlteration()  : mixed
Executes a specific alteration.
firstIsAlter()  : bool
Checks if a value is an Alter enum or an array starting with an Alter enum.
isChainedDefinition()  : bool
Detects if the definition represents chained alterations.

Properties

$alters

The enumeration of all definitions to alter on the array or object key/value properties.

public array<string|int, mixed> $alters = []

$container

The DI container reference.

public Container $container

Methods

alter()

Alters the given document (array or object) based on the configured `$alters` definitions.

public alter(mixed $document) : mixed

This method determines if the document is a sequential array (list). If it is, the alteration is recursively applied to each item. Otherwise (associative array or object), each key listed in $alters is processed.

Parameters
$document : mixed

The input to alter. Can be an associative array, object, or a list of items.

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
example
class Example
{
    use AlterDocumentTrait;

    public function __construct()
    {
        $this->alters =
        [
           'price' => Alter::FLOAT,
           'tags'  => [ Alter::ARRAY , Alter::CLEAN ],
           'name'  => [ Alter::TRIM , Alter::UPPERCASE ], // Chained alterations
        ];
    }
}

$input = [ 'price' => '19.99', 'tags'  => 'foo,bar', 'name' => '  john  ' ];

$processor = new Example();
$output = $processor->alter($input);

// $output:
// [
//     'price' => 19.99,
//     'tags'  => ['foo', 'bar'],
//     'name'  => 'JOHN',
// ]
Return values
mixed

The altered document, same structure as input.

alterArrayCleanProperty()

Clean an array of null or empty string elements.

public alterArrayCleanProperty(mixed $value[, bool &$modified = false ]) : array<string|int, mixed>|float
Parameters
$value : mixed
$modified : bool = false
Return values
array<string|int, mixed>|float

alterArrayElements()

Alters all elements in an array.

public alterArrayElements(array<string|int, mixed> $array[, array<string|int, mixed> $options = [] ][, Container|null $container = null ]) : array<string|int, mixed>
Parameters
$array : array<string|int, mixed>

The array reference to alter.

$options : array<string|int, mixed> = []

The options representation.

$container : Container|null = null

An optional DI container reference.

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
Return values
array<string|int, mixed>

alterArrayProperty()

Transform a string expression separated by semi-colon ';' to creates an array.

public alterArrayProperty(mixed $value[, array<string|int, mixed> $options = [] ][, Container|null $container = null ][, bool &$modified = false ]) : array<string|int, mixed>

You can chain multiple alter definition to transform the content of the array, ex:

Property::CATEGORY => [ Alter::ARRAY , Alter::CLEAN , Alter::JSON_PARSE ] ,

The previous example transform the 'category' string in an Array and after remove all null or empty array elements and JSON parse all elements.

Parameters
$value : mixed
$options : array<string|int, mixed> = []
$container : Container|null = null

An optional DI container reference.

$modified : bool = false
Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
Return values
array<string|int, mixed>

alterCallableProperty()

Call a function to alter a property.

public alterCallableProperty(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : mixed
Parameters
$value : mixed
$definition : array<string|int, mixed> = []
$modified : bool = false

alterFloatProperty()

Cast a value to float. If the value is an array, all elements in the array are casted.

public alterFloatProperty(mixed $value[, bool &$modified = false ]) : array<string|int, mixed>|float
Property::PRICE => [ Alter::FLOAT ] ,
Parameters
$value : mixed
$modified : bool = false
Return values
array<string|int, mixed>|float

alterGetDocument()

Gets a document with a Documents model.

public alterGetDocument(mixed $value[, array<string|int, mixed> $definition = [] ][, Container|null $container = null ][, bool &$modified = false ]) : mixed
Parameters
$value : mixed
$definition : array<string|int, mixed> = []
$container : Container|null = null

DI container for resolving base URL from service definitions.

$modified : bool = false
Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface

alterHydrateProperty()

Hydrate a property value into a specific class instance using reflection.

public alterHydrateProperty(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : mixed

This method transforms a raw value (typically an array) into an object of the specified class. If the input value is an array, it can be normalized and then hydrated using either the Thing constructor or the ReflectionTrait::hydrate() method depending on the class type.

Behavior

  • If $value is not an array, it is returned as-is.
  • If $value is an empty array, the method returns null (by default).
  • If $schema refers to a class extending Thing, the object is created directly via its constructor.
  • Otherwise, hydration is performed via ReflectionTrait::hydrate().
  • The $modified flag is set to true if the resulting value differs from the input.

Usage Example

Property::GEO => [ Alter::HYDRATE, GeoCoordinates::class ],

Custom Normalization

You can specify a custom normalization flag as a third element in the definition:

[ Alter::HYDRATE, GeoCoordinates::class, true , CleanFlag::ALL ]

By default, the value is normalized using: normalize() with flags CleanFlag::DEFAULT | CleanFlag::RETURN_NULL.

Parameters
$value : mixed

The original value to hydrate. Can be a scalar, array, or object.

$definition : array<string|int, mixed> = []

The alter definition, expected as:

[
    0 => string|null $schema,   // Fully qualified class name to hydrate into
    1 => bool        $normalize // Whether to normalize the value before hydration (default true)
    2 => int         $flags     // Optional CleanFlag bitmask
]
$modified : bool = false

Reference flag set to true if the resulting value differs from the original.

Tags
throws
ReflectionException

If an error occurs during reflection-based hydration.

Return values
mixed

The hydrated value, possibly an instance of $schema, or null if empty.

alterIntProperty()

Cast a value to integer.

public alterIntProperty(mixed $value[, bool &$modified = false ]) : array<string|int, mixed>|int

If the value is an array, all elements in the array are casted.

Property::PRICE => [ Alter::INT ] ,
Parameters
$value : mixed
$modified : bool = false
Return values
array<string|int, mixed>|int

alterJsonParseProperty()

Decodes a JSON string

public alterJsonParseProperty(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : string|false|null
Parameters
$value : mixed
$definition : array<string|int, mixed> = []
$modified : bool = false
Return values
string|false|null

alterJsonStringifyProperty()

Returns the JSON representation of a value

public alterJsonStringifyProperty(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : string|false|null
Parameters
$value : mixed
$definition : array<string|int, mixed> = []
$modified : bool = false
Return values
string|false|null

alterNormalizeProperty()

Normalize a document property using configurable flags.

public alterNormalizeProperty(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : mixed

The normalization can be customized via the $definition array:

  • If empty or no flags provided, uses CleanFlag::DEFAULT | CleanFlag::RETURN_NULL
  • If a flags value is provided at index 0, uses that instead
Parameters
$value : mixed

The value to normalize

$definition : array<string|int, mixed> = []

Optional flags array: [CleanFlag value, ...other params]

$modified : bool = false

Reference flag indicating if the value was modified

Tags
example
// Use default flags
$this->alterNormalizeProperty( $value );
// Uses: CleanFlag::DEFAULT | CleanFlag::RETURN_NULL

// Use custom flags
$this->alterNormalizeProperty($value, [ CleanFlag::NULLS | CleanFlag::EMPTY ] );

// Only remove nulls
$this->alterNormalizeProperty($value, [CleanFlag::NULLS]);
Return values
mixed

The normalized value, or null if cleaned away

alterNotProperty()

Invert a boolean value or an array of booleans.

public alterNotProperty(mixed $value[, bool &$modified = false ]) : bool|array<string|int, mixed>
Parameters
$value : mixed

The value to alter. Can be a boolean, array of booleans, or any other value.

$modified : bool = false

Reference flag set to true if the value is altered.

Tags
example
$processor = new class {
use \oihana\traits\alters\AlterNotPropertyTrait;
};

// Single boolean
$modified = false;
$result = $processor->alterNotProperty(true, $modified);
// $result === false
// $modified === true

// Array of booleans
$array = [true, false, true];
$result = $processor->alterNotProperty($array, $modified);
// $result === [false, true, false]
// $modified === true
Return values
bool|array<string|int, mixed>

Returns the inverted boolean or array of inverted booleans.

alterUrlProperty()

Generates a complete URL by combining path segments and document properties.

public alterUrlProperty(array<string|int, mixed>|object $document[, array<string|int, mixed> $options = [] ][, Container|null $container = null ][, bool &$modified = false ][, string $propertyName = null ][, string $containerKey = 'baseUrl' ]) : string

The method builds a URL in the following order:

  1. Resolves the base URL from the container (if containerKey is provided and not false)
  2. Joins the base URL with the provided path segment
  3. Appends the property value from the document
  4. Optionally adds a trailing slash

Parameters via $options array:

  • [0] (string) — Path segment to append after base URL (e.g., '/products', '/api/v1/users')
  • [1] (string) — Document property name containing the final segment (default: 'id')
  • [2] (string|bool) — Container service key for base URL resolution or false to skip (default: 'baseUrl')
  • [3] (bool) — Add trailing slash to the result (default: false)
Parameters
$document : array<string|int, mixed>|object

The document to read property values from.

$options : array<string|int, mixed> = []

Configuration array: [path, propertyName, containerKey, trailingSlash]

$container : Container|null = null

DI container for resolving base URL from service definitions.

$modified : bool = false

Reference flag set to true if URL alteration occurs.

$propertyName : string = null

Default property name to use if not specified in options.

$containerKey : string = 'baseUrl'

Default container key for base URL if not specified in options.

Tags
throws
DependencyException

If container service resolution fails.

throws
NotFoundException

If container service is not found.

Complete Example:

class DocumentMapper
{
    use AlterUrlPropertyTrait ;

    public function mapPlace( $document, $container )
{
        return $this->alterUrlProperty
(
            $document,
            ['/places', 'id', 'baseUrl', true],
            $modified,
            'id',
            $container,
            'baseUrl'
        );
    }
}

// With container containing: 'baseUrl' => 'https://api.example.com'
// And document: ['id' => 123]
// Result: 'https://api.example.com/places/123/'
Return values
string

The generated URL.

alterValue()

Replace a value with a new one if different, otherwise keep the original.

public alterValue(mixed $value[, array<string|int, mixed> $definition = [] ][, bool &$modified = false ]) : mixed
Parameters
$value : mixed

The original value

$definition : array<string|int, mixed> = []

The definition reference to extract the new value to apply.

$modified : bool = false

Will be set to true if the value was replaced

Return values
mixed

The altered value

initializeAlterKey()

Initialize the 'alters' property.

public initializeAlterKey([array<string|int, mixed> $init = [] ]) : static
Parameters
$init : array<string|int, mixed> = []
Return values
static

initializeAlters()

Initialize the 'alters' property.

public initializeAlters([array<string|int, mixed> $init = [] ]) : static
Parameters
$init : array<string|int, mixed> = []
Return values
static

alterProperty()

Alters a specific property of the given document using one or more transformation rules.

protected alterProperty(string $key, array<string|int, mixed>|object $document, string|array<string|int, mixed> $definition[, Container|null $container = null ]) : array<string|int, mixed>|object

The transformation is defined by the $definition argument, which can be:

  • A string representing a single Alter:: constant (e.g. Alter::FLOAT)
  • An array with a single alteration and parameters: [ Alter::URL , '/product/' ]
  • An array with chained alterations (NEW): [ Alter::NORMALIZE , [ Alter::HYDRATE , Class::class ] ]
  • An array with multiple simple alterations (NEW): [ Alter::TRIM , Alter::UPPERCASE , Alter::NORMALIZE ]

If the alteration modifies the value, the altered value is set back into the document. Otherwise, the original document is returned unmodified.

Supported alter types:

  • Alter::ARRAY — Explodes a string into an array (using ;) and applies sub-alters
  • Alter::CALL — Calls a user-defined callable on the value
  • Alter::CLEAN — Removes empty ("") or null elements from arrays
  • Alter::FLOAT — Casts the value to float
  • Alter::GET — Resolves a document by ID using a model
  • Alter::HYDRATE — Hydrate a value with a specific class.
  • Alter::INT — Casts the value to integer
  • Alter::JSON_PARSE — Parses a JSON string into a PHP value
  • Alter::JSON_STRINGIFY — Encodes a value into a JSON string
  • Alter::NORMALIZE — Normalize a document property using configurable flags
  • Alter::NOT — Invert boolean values
  • Alter::URL — Generates a URL based on document properties
  • Alter::VALUE — Replaces the value with a fixed constant
Parameters
$key : string

The name of the property to alter (e.g. 'price', 'tags')

$document : array<string|int, mixed>|object

The document (array or object) passed by reference

$definition : string|array<string|int, mixed>

The alteration definition: either a string (Alter::) or an array ([ Alter::X , ...args ])

$container : Container|null = null

An optional DI container reference.

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
example
$this->alters =
[
    'price'    => Alter::FLOAT,                         // Casts 'price' to float
    'tags'     => [ Alter::ARRAY , Alter::CLEAN ],      // Splits and cleans 'tags'
    'meta'     => [ Alter::JSON_PARSE ],                // Parses 'meta' JSON string
    'url'      => [ Alter::URL , '/product/' ],         // Generates a product URL
    'discount' => [ Alter::CALL , fn($v) => $v * 0.9 ], // Applies a callable
    'rating'   => [ Alter::VALUE , 5 ],                 // Fixed value replacement
    'geo'      => [ Alter::NORMALIZE , [ Alter::HYDRATE , GeoCoordinates::class ] ],
    'name'     => [ Alter::TRIM , Alter::UPPERCASE , Alter::NORMALIZE ],
];

$document =
[
    'price'    => '29.90',
    'tags'     => 'a;;b;',
    'meta'     => '{"active":true}',
    'url'      => '123',
    'discount' => 100,
    'rating'   => 0,
    'geo'      => ['latitude' => null, 'longitude' => 2.5],
    'name'     => '  john doe  ',
];

$result = $this->alterProperty('price', $document, Alter::FLOAT);
// Returns the document with 'price' casted to float (29.9)
Return values
array<string|int, mixed>|object

The altered document (same reference type as input)

applyChainedAlterations()

Applies chained alterations to a property.

protected applyChainedAlterations(string $key, array<string|int, mixed>|object $document, array<string|int, mixed> $definitions[, Container|null $container = null ]) : array<string|int, mixed>|object

Each alteration in the chain is applied sequentially, with the output of one becoming the input of the next.

Parameters
$key : string

The property key

$document : array<string|int, mixed>|object

The document containing the property

$definitions : array<string|int, mixed>

The array of alteration definitions

$container : Container|null = null

An optional DI container reference.

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
Return values
array<string|int, mixed>|object

$document The document with the altered property

applySingleAlteration()

Applies a single alteration (original behavior).

protected applySingleAlteration(string $key, array<string|int, mixed>|object $document, array<string|int, mixed> $definitions[, Container|null $container = null ]) : array<string|int, mixed>|object
Parameters
$key : string

The property key

$document : array<string|int, mixed>|object

The document containing the property

$definitions : array<string|int, mixed>

The alteration definition with parameters

$container : Container|null = null

An optional DI container reference.

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
Return values
array<string|int, mixed>|object

The document with the altered property

executeAlteration()

Executes a specific alteration.

protected executeAlteration(string|Alter $alter, string $key, mixed $value, array<string|int, mixed> $params, array<string|int, mixed>|object $document[, Container|null $container = null ][, bool &$modified = false ]) : mixed
Parameters
$alter : string|Alter

The alteration type

$key : string

The property key (for context)

$value : mixed

The value to alter

$params : array<string|int, mixed>

The alteration parameters

$document : array<string|int, mixed>|object

The full document (for context)

$container : Container|null = null

An optional DI container reference.

$modified : bool = false

Output parameter indicating if the value was modified

Tags
throws
ContainerExceptionInterface
throws
DependencyException
throws
NotFoundException
throws
NotFoundExceptionInterface
throws
ReflectionException
Return values
mixed

The altered value

firstIsAlter()

Checks if a value is an Alter enum or an array starting with an Alter enum.

protected firstIsAlter(mixed $first) : bool
Parameters
$first : mixed

The value to check

Return values
bool

True if it's an Alter or array with Alter as first element

isChainedDefinition()

Detects if the definition represents chained alterations.

protected isChainedDefinition(array<string|int, mixed> $definitions) : bool

Chaining is detected when:

  • The first element is an Alter enum
  • AND the second element is either:
    • Another Alter enum (simple chaining)
    • An array whose first element is an Alter enum (chaining with params)
Parameters
$definitions : array<string|int, mixed>

The alteration definitions

Return values
bool

True if chaining is detected, false otherwise


        
On this page

Search results