Standard Core Libraries
SPL extensions, array utilities, error handlers, and more.
Introduction
Standard Core Libraries is sets of useful basic libraries and helpers. these libraries are used as part of core functionalities of Poirot Framework. The component are distributed under the "Poirot/Std" namespace and has a git repository, and, for the php components, a light autoloader and composer support. All Poirot components following the PSR-4 convention for namespace related to directory structure and so, can be loaded using any modern framework autoloader. 100% Test Coverage and fully testable by PHPUnit Test.
In Case You need any support or question use the links below:
Slack: getpoirot.slack.com https://join.slack.com/t/getpoirot/shared_invite/zt-dvfhkoes-h45XoKlyxamfhaHm6G4uSA
Arguments Resolver
It helps to automatically call a callable (function, method or closure) or create an instance of a class with providing necessary arguments from list of available options.
Resolver can resolve arguments by argument name, or type hint provided to the argument. Argument name has the most priority, if name is not match within provided options then try to match based on the type hint of argument by searching from the first element to last options and find the match.
function foo(array $array, stdClass $object, callable $callable, array $secondArray) {}
$ar = new ArgumentsResolver(new CallableResolver('foo'));
$args = $ar->withOptions([
function () {},
['second' => ''],
new stdClass(),
'array' => [],
])->getResolvedArguments();
/*
[
'array' => [],
'object' => object(stdClass)
'callable' => object(Closure)
'secondArray' => ['second' => '']
]
*/Class Instantiator
Create an instance of class and resolve the arguments needed to constructing object by available given options.
or simply use the global function available to create instance of class:
Callable Resolver
Allows to determine the arguments to pass to a function or method and call it. The input to the resolver can be any callable.
Usage:
Resolve to callable arguments as an array:
Call callable dynamically by list of available arguments: this will resolve the arguments list needed to execute callable and wrap it to the \Closure that can be invoked directly. The codes below is equivalent as the code block that you can find above.
or simply use the available global function helper:
Reflection Resolver
There is also an utility class which helps in creating a reflection instance: The input can be any callable.
Configurable
Configurable objects are classes which implemented ipConfigurable pact interface, which allow object to parse configuration properties from a resource to an iterator and build the object itself with this given properties.
Register custom config parser
Parser can be registered globally for classes which extends aConfigurable each registered parser should implement iConfigParser interface. here is an example of registering json parser for imaginary Application Configurable class.
Configurable setter
Built-in configurable which map whole properties to a setter method defined inside the class and feed them by calling setter method and associated value of given property.
This is the simple demonstration of what is expected of a configurable object:
Multi Parameter Setter Methods
If the setter method needs to have more than one value as a parameter the easiest way is to pass required parameters as an iterable or array to a method. with configurableSetter it's possible to define parameters needed for a setting as a separate arguments to the setter method.
Avoid configuration exceptions
Exceptions of type ConfigurationError expected to thrown when something is not correct with given configuration properties. for example when given property is unknown (UnknownConfigurationPropertyError) for configurable object or the given value has not correct type (ConfigurationPropertyTypeError).
During building object throwing these known exceptions can be eliminated and skipped.
Environment configuration
To ease apply different PHP runtime configurations at once the iEnvironmentContext interface is defined which can hold various possible runtime configuration values.
This contexts can be considered as different environments with different setup for a specific purpose. such as Development, Test or Production setup.
Simple usage
Available configurations
Here is the list of available configuration provisioning attributes and their corresponding built-in php command:
Attribute
Value
Equivalent PHP Command
define_const
array(['const_name' => 'value'])
define((string) $const, $value);
display_errors
(int) 0, 1
ini_set('display_errors', $value);
display_startup_errors
(int) 0, 1
ini_set('display_startup_errors', $value);
env_global
array(['env_name' => 'value'])
$_ENV[$name] = $value; //simplified
error_reporting
error_reporting(E_ALL);
html_errors
(int) 0, 1
ini_set('html_errors', $value);
max_execution_time
(int) 30
set_time_limit($seconds)
PreDefined Contexts
Development, Will enable all error reporting level to show to end-user.
Production, to mitigate all error messages to display to end user.
PhpServer, will give the current values from php server configuration.
Environment Context Registry
Environment context values can be override while registry provision configurations.
after applying environment context it's accessible from registry anytime.
Custom environment context
It's possible to register an actual context with different aliases naming or create a new context which implementing iEnvironmentContext interface.
Alias naming of existing contexts:
Custom context implementation:
Error Handler
It's a wrapper around default php set_error_handler and set_exception_handler functions. it can be used to create a custom error handler that lets you control how PHP behave when some runtime errors happens. With different error types custom error handling can handle only errors were expecting and take the appropriate action based on that.
Simple usage
Custom error handler
ErrorHandler::handle takes the callable as it's second parameter, and it servers to notify PHP that if there are any php runtime errors.
Callable expected to get \ErrorException object as all errors will converted to by error handler.
Error level handling
First argument of ErrorHandler lets you choose what errors should handled, and it works like the error_reporting directive in php.ini. However, it's important to remember that you can only have one active error handler at any time, not one for each level of error.
By default error handler will not catch errors that is silenced by error_reporting level otherwise we use a specific bit control flag ErrorHandler::E_ScreamAll
There is a special bit mask flag ErrorHandler::E_ScreamAll that can be added to error level handling to catch all errors if accrued regardless of what php error reporting level is.
Handle Exceptions
As exceptions terminate the execution flow there is no much control over Exception handling the only thing is triggering callable registered in chain.
Hydrator
Hydrator provide a mechanisms both for mostly extracting data sets from objects, as well as manipulating objects data. A simple example of when hydrators came handy is when user send form data from website these data can be in different naming as we expect in domain logic and probably doing some filter over data as they are not trusted usually.
Entity Hydrator
Entity Hydrator abstract basically separate manipulation and extraction to two different job, with defined setter methods hydrator object can be manipulated with given data set then based on the given data we have getter methods which is expected to filter and extract prepared data for next stage to receiver of data.
Register global input data parser: with data parsers it's possible to parse different data types to an iterator to feed into entity hydrators to related setter method.
Getters hydrator
extract data from an object with getter methods, generally getter hydrator will make an Reflection object of class find getter methods and iterate them by calling them method and return the sanitaized property name associated with the value returned from method call.
Some property methods can be excluded to not considered as data:
Excluding properties can be defined as well internally into class by notations:
IteratorWrapper
This iterator wrapper allows the conversion of anything that is Traversable into an Iterator. This class provide a wrapper around any php Traversable and adding extra functionalities to that.
Manipulating key and values
On iterator callback the returned value will considered as a current value of iterator item:
we also can change the key if we need to do this:
Filter items
With iterator wrapper we can skip unwanted items from the iterator with provide Closure control how we iterate over object.
Cutout items
Sometimes it's needed to stop iterating over items when specific conditions met before we get to the end of iterator items. like when we have limit on database result items.
Caching Iterator
As we have built-in support for CachingIterator but IteratorWrapper itself comes with the internal caching support to the iteration. Some times you have an iterator which is not iterable multiple times for instance it could be the case when you fetch result from databases like MangoDB which you cant rewind the iteration. here is the example can illustrating this better:
MutexLock
The Mutex allows mutual execution of concurrent processes in order to prevent "race conditions". This is achieved by using a "lock" mechanism. Each possibly concurrent thread cooperates by acquiring a lock before accessing the corresponding data.
Usage example:
How to instantiate lock for specific resource:
here we created an instantiate of lock object which is try to make lock file on given $lockDir path, the $realm is an indicator and unique name to our lock resource.
MutexLock::giveLockDirPath is an Immutable method so when we gave the path we couldn't change the value later on.
Object can acquire lock multiple times
When object is already acquire lock on resource all further tries to lock from same object will be success:
Different lock object instances can't acquire lock on same resource
If we create different lock objects with same setup lock will not acquired on second calls if resource is already got locked.
Releasing lock, cleanup and destructing object
As the crash could happen to PHP while we acquired lock the resource might kept as locked as execution didn't reach the __destruct method of lock object. we always allow MutexLock to release on resources.
We need a system that cleans the garbage in case of crash, just like PHP does for everything else. register_shutdown_function() could cover the cases of exit(), die() and other exceptions in the code code, but it wouldn’t be enough for a crash or an interruption.
Expiration TTL on lock
The TTL expiration on seconds amount of time can be defined to keep lock on resource.
ResponderChain
The ResponderChain allows to run multiple callable one after other and pass the result from each callable to others to attain to the final result.
Default Chaining Result Behaviour
Merging values
By default if value returned from callable is array or StdArray object will get merged to previous result regardless if the previous result is array, StdArray or not.
Replacing values
Any value other than array or StdArray returned by callable will replace the result from previous callable regardless if the previous result is arrayor not.
Another example to demonstrate merge and replace together:
Key Value Pair Result
The KeyValueResult object can be returned by the callable to indicate that value is an key, value pair result which a key holding the value associated with that.
The KeyValueResult will not get merged by the previous value and always replace the last one and will cast to a single key associative array at the end.
Instead regular array this result won't get merged by last result from chain:
Aggregate Result
The AggregateResult will accept a variadic arguments of any data result implementation or any PHP default data type and merge them together, the final result is a multi key / value pair array.
The AggregateResult will not get merged by the previous value and always replace the last result.
The AggregateResult respond result won't get merged by last result from chain:
Merge Result
When result from callable is MergeResult will merge the data from last result, it's similar to simple array type behaviour when it's returned by callable.
Passing Parameters Through Call Chain
After each callable execution returned result get merged to params and will get resolved by type and name of argument to next callable.
Define Default Parameters
default parameters can be set on creation time, these parameters can be resolved to callable which required the parameter by defining an argument with same type or name to callable. to read more about resolving arguments see ArgumentsResolver.
Parameters get updated based on each result from callable
Every result returned by each callable will get merged to the default parameters and will replace if the current parameters with same name exists then these parameters can be resolved to next callable.
Exception Handling
With onFailure method the callable can be assigned to a callable chain which will be executed, the \Exception which is thrown and other parameters will be resolved to given callable.
Validator abstraction
Validation is a very common task while we dealing with Data, Data can come from forms submitted by users or data before it is written into a database or passed to other web service. Any object can implement Validator abstraction interface and trait which makes validation task transparent by providing an abstraction layer to generalize the validation. any Validation libraries can still be use out of the box to ease validation task or just simple php code block.
Usage example
The only task of objects implementing validation abstract is to add ValidationError object as error(s) which found during validation.
Error chain
Each error caught by validator will chained together as an exception which is traversable by getting the previous exception chain.
Error message processor
Validation error messages are usually shows to users directly, depends of different scenarios we might wanted to show different messages to end user like translating error messages.
There is some samples of error messages processors which give you the whole idea of how to use them.
Default registered message processor will replace %param% and %value% with ValidatorError into error message.
Any custom message processor can be attached statically to the ValidationError class.
Last updated
Was this helpful?