📜 ⬆️ ⬇️

A magic object for storing and transmitting heterogeneous data with type and value checking

In PHP, for storing and transferring heterogeneous data (component configurations, parameter sets for functions, options for widgets, etc.) arrays are usually used - their versatility and ease of use greatly contributes to this, but this causes the following problems:

  1. When developing even in advanced IDE (development systems) and when executing an application, there is no control over the structure and data types in the array.
  2. IDE can do nothing to help with development, so that the names of possible array keys will have to be remembered-typed or somewhere searched-copied-pasted, which, apart from inconvenience and poor performance, increases the likelihood of a typo.
  3. It is difficult to control where the individual elements of this array are used and, accordingly, it is difficult to refactor, even despite the power of modern IDEs.


For small projects, these problems may still be insignificant, it is easier to control everything there, but as the amount of code grows, they become more noticeable.

')
One of the well-known approaches that solves problems 2 and 3 is the creation of objects based on such pseudo-classes extending stdClass. The class properties described in PHPDoc and specifying wherever an object of its class is used (in PHPDoc) allows the autocomplete to work and check possible property names, control where properties are applied and, if necessary, easily refactor them:
/** * @property integer $integer * @property integer[] $integers */ class DataStorage extend stdClass { } $ds=new DataStorage; $ds->integer=13; $ds->integers=[1,2,3]; 

But the problem with the control of values ​​is not solved this way, the IDE does not control the data that came from outside, not to mention that someone can ignore a warning in the IDE, as a result, incorrect data can lead to an unexpected error in an unexpected place. In addition, as far as I know, PHPDoc does not yet allow you to specify a list of possible property values, which is often important.

Add some PHP magic: StrictDataStorage

Not finding a suitable solution to these problems, I developed a class that allows you to perform data checking based on PHPDoc, while also checking the values ​​as an additional bonus by the list of possible ones. The class works similarly to the solution given above with stdClass - a class inherited from StrictDataStorage is created and its @property types are described in PHPDoc via @property . When assigning values ​​to properties, values ​​are checked for compliance with the type described and by the result of the check, either an assignment occurs or an error handler is triggered — an exception is thrown by default. When checking supports all phpdoc data types except callable, the enumeration of several possible types through | and arrays described by [] at the end of the type.
In addition to the @property element, @enum and @options .

@enum

Allows you to specify a list of possible values ​​for the property. The study of information available on the Internet has led to the conclusion that there is currently no standard or even an agreement on this issue, so for the time being it has come up with its own version that does not conflict with @property . The @enum syntax @enum similar to @property - first comes the description of possible values, then the name of the property. Possible values ​​are specified in two ways.
  1. A list in square brackets - the contents of the brackets can be disassembled via json_decode (), therefore it should be in format, which means, first of all, the use of double quotes for framing strings.
  2. By the name of the class in which the values ​​are stored, this class must support the EnumArrayableInterface interface, which lies in the same repository. In principle, SplEnum support can be made.


@options

Contains class operation settings separated by commas, currently two values ​​are supported:


Example

The class StrictDataStorage is laid out here github.com/Yannn/php-strict-data , as it works I will illustrate with the example of the successor SampleDataStorage given in the same place:
 <?php /** * @property integer $integer * @property Closure $callback * @property mixed $mixed * * @property integer[] $integers * @enum SampleEnum[] $integers * * @property float|string $enumFloat * @enum ["1.8","7","9"] $enumFloat * * @property string[] $enumArray * @enum ["one","two"][] $enumArray * * @options PhpDocNotRequired|StrictNumberTypeCheck */ class SampleDataStorage extends StrictDataStorage { } 

Since specified @options PhpDocNotRequired for an object of the SampleDataStorage class you can assign a value to any property, but if you assign the properties $ integer, $ callback, $ mixed, $ integers, $ enumFloat, $ enumArray, the values ​​will be checked according to the rules described in @property and @enum :

If the value does not correspond to the specified rules, an exception will be raised. Methods that handle errors are implemented as protected, so that the behavior when an error is easily changed by inheritance.

Compatibility Requirements

Since I have been using PHP 5.4 for a long time, and the class requires PHP> = 5.4; there seems to be no other special requirements.

I would be happy for comments, suggestions and of course bugreports.

Source: https://habr.com/ru/post/234433/


All Articles