- PVSM.RU - https://www.pvsm.ru -
В PHP для хранения и передачи разнородных данных (конфигурации компонентов, наборы параметров для функций, опции для виджетов и т.п.) обычно используют массивы — их универсальность и легкость использования весьма способствует этому, однако при этом возникают следующие проблемы:
Для небольших проектов эти проблемы могут быть еще несущественны, там проще все проконтролировать, но с ростом объема кода они становятся все заметнее.
Один из известных подходов который позволяет решить проблемы 2 и 3 — создание объектов на основе этаких псевдоклассов расширяющих stdClass. Описанные в PHPDoc свойства класса и указание везде где используется объект его класса (в PHPDoc) позволяет работать автокомплиту и проверке возможных имен свойств, контролировать места применения свойств и при необходимости легко их рефакторить:
/**
* @property integer $integer
* @property integer[] $integers
*/
class DataStorage extend stdClass{
}
$ds=new DataStorage;
$ds->integer=13;
$ds->integers=[1,2,3];
Но проблема с контролем значений так не решается, данные пришедшие извне IDE точно не проконтролирует, не говоря уж о том, что предупреждение в IDE кто-то может и проигнорировать, в результате неверные данные могут привести к неожиданной ошибке в неожиданном месте. Кроме того, насколько мне известно, PHPDoc пока что не позволяет указывать список возможных значений свойств, что часто бывает важно.
Не найдя подходящего решения этих проблем разработал класс который позволяет выполнять проверку данных на основе PHPDoc, при этом как дополнительный бонус проверяет значения и по списку возможных. Работает класс аналогично решению приведенному выше с stdClass — создается класс отнаследованный от StrictDataStorage и у него в PHPDoc через @property
описываются типы свойств. При присвоение значений свойствам производится проверка значений на соответствие типа описанному и по результату проверки или происходит присвоение, или срабатывает обработчик ошибки — по умолчанию выбрасывается исключение. При проверке поддерживает все типы данных PHPDoc кроме callable, перечисление нескольких возможных типов через | и массивы описанные через [] в конце типа.
Кроме элемента @property
обрабатывается @enum
и @options
.
@enum
Позволяет указывать список возможных значений свойства. Исследование имеющейся в интернете информации привело к выводу, что никакого стандарта и даже просто соглашения по этому поводу на настоящий момент не существует, поэтому пока что придумал свой вариант не конфликтующий с @property
. Синтаксис @enum
похож на @property
— сначала идет описание возможных значений, потом название свойства. Возможные значения указываются двумя способами
@options
Содержит настройки работы класса через запятую, в настоящий момент поддерживается два значения:
@enum
или @property
, то ему невозможно присвоить значение, наличие PhpDocNotRequired в @options
включает менее строгий режим проверки — свойство м.б. присвоено даже если не описано. Этот режим позволяет описывать только те свойства для которых важна проверка значения.@options
активирует более строгий режим проверки чисел — строки не пройдут!Класс StrictDataStorage выложен здесь github.com/Yannn/php-strict-data [1], как он работает проиллюстрирую на примере приведенного там же наследника SampleDataStorage:
<?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
{
}
Т.к. указано @options PhpDocNotRequired
у объекта класса SampleDataStorage можно присвоить значение любому свойству, но при присвоении свойств $integer, $callback, $mixed, $integers, $enumFloat, $enumArray значения будут проверятся по описанным в @property
и @enum
правилам:
@options
значение StrictNumberTypeCheck, то можно будет присвоить строку содержащую целое число.["1.8","7","9"]
.["one","two"]
.При несоответствии значения указанным правилам будет выкидываться исключение. Методы обрабатывающие ошибки реализованы как protected, так что поведение при ошибке легко изменить наследованием.
Буду рад замечаниям, предложениям и конечно же багрепортам.
Автор: annenkov
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/68224
Ссылки в тексте:
[1] github.com/Yannn/php-strict-data: https://github.com/Yannn/php-strict-data
[2] Источник: http://habrahabr.ru/post/234433/
Нажмите здесь для печати.