Standard Data Structures

Introduction

Standard Data Structures is sets of data manipulation objects and data entities structure which provide functionalities to ease working with data sets. 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

iData Interface

The iData interface provide simple interface around objects which considered as providing data properties with all objects implementing iData interface it's possible to exchange data between any data entity object.

Data Objects are: - Traversable - Countable - Implementing iObject property overloading interface.


interface iData
    extends iObject, \Countable
{
    /**
     * Set Struct Data From Array
     *
     * @param iterable $data
     *
     * @return $this
     */
    function import(iterable $data);

    /**
     * If a variable is declared
     *
     * @param mixed $key
     *
     * @return bool
     */
    function has(...$key);

    /**
     * Unset a given variable
     *
     * @param mixed $key
     *
     * @return $this
     */
    function del(...$key);

    /**
     * Clear all values
     *
     * @return $this
     */
    function empty();

    /**
     * Is Empty?
     *
     * @return bool
     */
    function isEmpty();
}

DataStruct

Implementing iData interface and is a simplest data entity object.

Constructing

The DataStructure can accept sets of data as a constructor argument. These data is an iterable object with key as data property name which hold the value of the property.

Constructing by variable reference

When there is an array variable, this can be referenced as a construct to the data object, make any change to the data object properties will reflect the reference variable.

It's Traversable

It's Countable

Data Manipulation, property overloading

Set Properties:

Get Properties value:

Remove property:

Check availability of property:

Note: if property exists and has null as value it also considered as available property and this method will return true.

Properties are accessible by memory reference

Data property can be reserved by it's memory reference: the property with not assigned value will not considered as property until take a value.

import - Set data to object

The import method will replace all existing property values by new values provided to method.

del - Remove property

Any given properties to method will be removed from data object.

has - Check property exists

Check whether any properties given as argument exists or not? If any of given properties exists will return true otherwise false will be returned.

Note: if property exists and has null as value it also considered as available property and this method will return true.

empty - Remove all properties

isEmpty - Check has any properties

The isEmpty method will check if object has any property and return boolean value.

DataTypedSet

The DataTypedSet is extending DataStruct and have all functionalities from that and in addition have some unique functionalities in general can be used to define custom property accessors which known as Getter/Setter methods. A getter is a method that gets the value of a specific property. On the other hand, a setter is a method that sets the value of a specific property. You don't need to use getter/setter for everything and they should used wisely only when it's needed. They might needed to be used when you have for example a property were accept only a specific PHP type. The date_time_created property can be one of those which only accept a \DateTime object.

Read-only properties

Read-only properties are created by defining only a getter method for a property. A PropertyIsGetterOnlyError exception is thrown in attempt to set a read-only property.

Methods with protected visibility which are prefixed with get, has and is all determined as the property getter. like: getPropertyName(), hasAnyOrder(), isAdministration(). Note: adding docblock for property is not mandatory but it's recommended.

Protect construct level properties by Read-only

Read-only properties are often used to provide read access to a property that was provided during construct, which should stay unchanged during the life time of an instance.

In this example below, we can have access to the connection used by Model class afterward and options is used by class itself for some internal usage inside the class and it's not a property accessor.

Write-only properties

Read-only properties are created by defining only a setter method for a property. A PropertyIsSetterOnlyError exception is thrown in attempt to get a write-only property.

Methods with protected visibility which are prefixed with set, give all determined as the property getter. like: setPropertyName($name), giveConnection($connection). Note: adding docblock for property is not mandatory but it's recommended.

Property Type declaration

Type declarations allow property to require a certain type at setter/getter level but mostly it would define on setters. On set property value the PropertyError will thrown if value type is mismatch by method arguments definition. When type declaration not happen on method argument and check happen inside the method block for given type and it's not match the PropertyTypeError expected to thrown as well.

When using Type Declaration the method argument should be nullable. it's needed when we gonna to unset or remove property by unseting property the underlying value will set to null.

import - Set data to object

The import method will replace all existing property values by new values provided to method.

As DataTypedSet could be sensitive to data given to properties couple of exceptions can happen when importing data.

Here is an example how the exceptions can be ignored while importing data:

more methods ...

The DataTypedSet is extending DataStruct and they have same functionalities except methods mentioned above hereto know more about available methods check the documentation from DataStruct .

DataHashMap

The DataTypedSet is extending DataStruct and have all similar functionalities from that. what specific is about hash map data object is allow to set none scalar keys for data.

As none scalar types can be assigned as a key holding values there is no possibility to use property accessors, so two methods are added to DataHashMap object:

set - Set property

get - Get property

del - Remove property

has - Check property exists

more methods ...

The DataTypedSet is extending DataStruct and have all functionalities from that to know more about available methods check the documentation from DataStruct .

CollectionObject

The CollectionObject is using to store any kind of data type in a collection set, it's possible to define set of meta data to it when data is stored, which can used to query the whole data based on theses associated meta data. for every same data a unique datum id will be generated which is used as a reference to fetch data again.

It's Countable

ObjectID for data type

Every object when stored to the collection will get a unique ID and can be used to access to the object. here is how the uniqueID can be generated in forehand for an object.

add - Adding data

Add data to the collection, data can be any value type. with the second argument it's possible to define set of meta data to the stored data which can fetched later or used as a term when querying the collection.

Note: when same Data is exists in collection the meta data will be replaced with the given meta data in add method.

get - Get stored object by objectId

Get stored object data in collection by its unique object id, will return null if not found.

Get additional meta data associated with the object: with a second argument the meta data and object itself is available to the callback function. if object with given id not exists in collection null will returned without calling the given callback function.

find - Find an object by meta data

Search for stored objects that match given accurate meta data. The result returned is the IteratorWrapper instance include all the object matched with the criteria data.

Fetch all objects inside collection:

Find based on the criteria matching the metadata associated with each object:

del - Remove object from collection

Remove an object by the ObjectID. if no object with same ObjectID exists on collection it will do nothing.

setMetaData - Set object meta data

Set meta data associated with the existence object. It will thrown an Exception if object not found.

CollectionPriorityObject

The CollectionPriorityObject is extending CollectionObject to allow add objects with priority order. To read about all available methods see the CollectionObject.

add - Adding data

The third argument of add method indicate the priority order of the object.

priority order also can be defined as the meta data:

more methods ...

More methods is similar with CollectionObject, To read about all available methods see the CollectionObject documentation.

Value Object Abstraction

In practical terms you can think of value objects as your own primitive types. And they should behave as ones. It means that value objects should always be immutable! This is crucial otherwise it’s hard to avoid issues with values changing unexpectedly (values should be replaced, not modified!).

It’s important to remember about immutability (none of these methods can modify internal state) and to not to put any actual business logic inside value objects – they should be as self-contained as possible.

Declaration

To define a value object of any type it should extends the aValueObject abstract class, and you should follow these simple rules when working with ValueObject in Poirot:

Constructor:

  • Value Object will have __construct method.

  • Constructor method should have all possible Value Object needed properties as arguments in constructor method.

  • Each constructor arguments should have an accessor method with same name of argument. for example, if you have $amount variable it should have one protected accessor method named withAmount($value) which can change the state of object for the property.

  • The parent __construct method call on constructing object to initialize the init state.

Validation:

When creating a new value object we need to make sure that it has a valid state on constructing. when values are not correct Exception should thrown on creating object. To read more see Validation section.

Getting current state properties:

To know what state Value Object is and to get property values that we need to be expose to outside the getter methods can be defined:

Change object state and immutability:

Changing the object state and immutability will handled by abstract class the only thing is to define an accessor protected method that is prefixed by with. Check the example below and how it's been used:

to make it understandable to most IDEs some notations can be added to class:

It's Traversable

It's Serializable

Check equality

Two value objects are equal not when they refer to the same object, but when the value that they hold is equal, e.g. two different one hundred dollar bills have the same value when we use them to buy something (class Money would be a value object). To check equality of two value object the abstract object will check the whole values one by one and the class implementation to see if the given object is extend the current value object, which mean something similar to this method:

The isEqualTo method can be override by object extending abstract value object, for the Money object it could be re written:

Validation

Let’s take currency from our Money object, Currency value should always consist of three uppercase letters, so why not to convert it to its own Value Object:

Validation should happen on construct level and when value object state got changed by property accessor as well.

Here we only make sure that currency code has a correct format, but as an improvement it could also validated against ISO 4217 currency list (or its subset).

Additional helper methods

In addition to standard getter methods for internal state retrieval, VOs can have helper methods with various functionality. This includes creating new values (either entirely new or based on the current one, e.g. result of adding some amount to Money object), providing different representation for its internal state (e.g. IPAddress VO can present IP address as string or binary data), checking if value object meets some condition (e.g. DateRange VO can have a method to find out if it overlaps another DateRange object), etc.

PriorityQueue

A PriorityQueue is very similar to a Queue. Values are pushed into the queue with an assigned priority, and the value with the highest priority will always be at the front of the queue. The PHP Default SplPriorityQueue acts as a heap; on iteration, each item is removed from the queue. This class will allow to iterate multiple time over internal queue which is implemented default php SplPriorityQueue.

Iterating over a Queue and successive pop operations will not remove items from the queue.

Simple Usage

The PriorityQueue only has a method insert and provide Traversable object to travers over the items in queue without deleting them.

SplQueue

There is some workaround and fixes for default PHP SplPriorityQueue which is available as these classes. these two classes are extend SplPriorityQueue and used internally by PriorityQueue.

SplDescendingQueue

SplAscendingQueue

Last updated

Was this helpful?