Php создать свой тип данных

Php создать свой тип данных

PHP uses a nominal type system with a strong behavioral subtyping relation. The subtyping relation is checked at compile time whereas the verification of types is dynamically checked at run time.

PHP’s type system supports various base types that can be composed together to create more complex types. Some of these types can be written as type declarations.

Base types

Some base types are built-in types which are tightly integrated with the language and cannot be reproduced with user defined types.

  • Built-in types
    • null type
    • Scalar types:
      • bool type
      • int type
      • float type
      • string type
      • false
      • true
      • Interfaces
      • Classes
      • Enumerations

      Composite types

      It is possible to combine simple types into composite types. PHP allows types to be combined in the following ways:

      Intersection types

      An intersection type accepts values which satisfies multiple class-type declarations, rather than a single one. Individual types which form the intersection type are joined by the & symbol. Therefore, an intersection type comprised of the types T , U , and V will be written as T&U&V .

      Union types

      A union type accepts values of multiple different types, rather than a single one. Individual types which form the union type are joined by the | symbol. Therefore, a union type comprised of the types T , U , and V will be written as T|U|V . If one of the types is an intersection type, it needs to be bracketed with parenthesis for it to written in DNF : T|(X&Y) .

      Type aliases

      PHP supports two type aliases: mixed and iterable which corresponds to the union type of object|resource|array|string|float|int|bool|null and Traversable|array respectively.

      Note: PHP does not support user-defined type aliases.

      Источник

      Пользовательские типы в PHP

      В отношении данных, которые программа получает извне, принято следовать правилу trustno1. Это справедливо не только в отношении данных, получаемых непосредственно от пользователя, но и в отношении данных, которые передаёт в подпрограммы клиентский код.

      PHP 7 оснащён расширенной системой контроля типов аргументов, включающей не только классы, но и скаляры. Однако в том, что касается сложных структур данных, ничего не изменилось — для них существует единственный тип array, который в PHP может содержать всё, что угодно.

      Я надеюсь, что новые версии PHP исправят ситуацию. А на данный момент я хочу поделиться с сообществом некоторыми своими наработками в этой области:

      image

      UPD 02.12.2018 — Публикация была обновлена для соответствия приведённой документации текущим версиям библиотек.

      Fulltype

      Эта библиотека предназначена непосредственно для работы с типами. Вы можете определить собственный тип данных с помощью функции ArsMnemonica\Fulltype\fulltype::define:

      function define(string $aName, TypeInterface $aType): TypeInterface;

      Вы можете как создать и инстанцировать собственный класс, реализующий интерфейс ArsMnemonica\Fulltype\TypeInterface, так и использовать встроенные.

      Для обращения к типу предназначена функция ArsMnemonica\Fulltype\fulltype::type:

      function type(string $aName): TypeInterface;

      Она принимает в качестве аргумента имя типа (аргумент aName функции define), и возвращает соответствующий объект.

      Чтобы проверить значение на соответствие типу, воспользуйтесь функцией ArsMnemonica\Fulltype\fulltype::is:

      function is($aValue, TypeInterface $aType): bool;

      или методом validate самого объекта типа:

      function TypeInterface::validate($aValue): bool;

      Чтобы проверить значение на соответствие типу, вы также можете воспользоваться функцией ArsMnemonica\Fulltype\fulltype::assert:

      function assert($aValue, TypeInterface $aType): mixed;

      Эта функция возвращает переданное ей значение $aValue в случае успешной проверки, или выбрасывает исключение, унаследованное от TypeError, сообщение которого содержит описание переданного значения и место вызова функции assert.

      Определены следующие встроенные типы (пространство имён ArsMnemonica\Fulltype и класс fulltype):

      function bool(): BooleanType;

      Логическое значение true/false.

      function number(float $aMin = null, float $aMax = null): NumericType; function int(int $aMin = null, int $aMax = null): IntegerType; function cardinal(int $aMax = null): CardinalType;

      Тип NumericType соответствует PHP-типам int и float.

      Являющийся его наследником тип IntegerType соответствует только PHP-типу int.

      Оба типа могут быть ограничены минимальным и максимальным значениями.

      Тип CardinalType, являющийся наследником IntType, соответствует количественным числам (целым числам без знака) — его минимальным значением является 0, а максимальное может быть определено.

      function string(int $aLength = null): StringType;

      Строковый тип, может быть ограничен по максимальной длине.

      function regexp(string $aRegularExpression): RegularExpressionType;
      function enum(. $aValues): EnumerableType;

      Ограничивает множество допустимых значений заданным набором.

      function object(string $aBase = null): ObjectType;

      Значение может быть только объектом заданного класса (интерфейсы так же допустимы).

      function null(TypeInterface $aType): NullableType;

      Дополняет множество допустимых значений дочернего типа значением null.

      function array(int $aLength = null): ArrayType;

      Массивный тип (ключевое слово array не допустимо в качестве имени функции), может быть ограничен по максимальной длине.

      Значение может быть:
      — массивом;
      — объектом, реализующим интерфейсы ArrayAccess, Countable и Traversable (должен быть вызван метод objective).

      Чтобы задать допустимый тип значений массива, используйте метод of(TypeInterface), а для ключей используйте метод by(TypeInterface). Если вы зададите тип ключей, отличный от PHP-типов int и string, массивный тип будет иметь смысл только в отношении объектов, поскольку у массивов PHP не может быть ключей других типов.

      function any(TypeInterface . $aTypes): MultipleType;

      Структурный тип, требующий соответствия переданного для валидации значения хотя бы одному из дочерних типов.

      function union(TypeInterface . $aTypes): ExclusiveType;

      Структурный тип, требующий соответствия переданного для валидации значения строго одному из дочерних типов.

      function struct(TypeInterface . $aTypes): ComplexType;

      Структурный тип, требующий соответствия переданного для валидации значения всем дочерним типам.

      Для данного типа имеет смысл задавать следующие дочерние типы:

      function key(string $aName, TypeInterface $aType = null): PropertyType

      Тип-ключ, требующее от переданного для валидации значения быть массивом, содержащим строковый ключ указанного типа.

      function offset(string $aName, TypeInterface $aType = null): PropertyType

      Тип-смещение, требующее от переданного для валидации значения быть массивом или объектом, реализующим интерфейс ArrayAccess, содержащим строковое смещение указанного типа.

      function property(string $aName, TypeInterface $aType = null): PropertyType

      Тип-свойство, требующее от переданного для валидации значения быть объектом, содержащим свойство указанного типа.

      Если для указанных выше типов вызван метод optional, то соответствующая проверка допускает отсутствие такого ключа/смещения/свойства.

      Для наглядной демонстрации работы библиотеки рассмотрим следующий пример:

      use ArsMnemonica\Fulltype\fulltype as t; const input_t = 'input'; t::define(input_t, t::struct( t::key('name', t::string()), t::key('authors', t::any( t::string(), t::array()->of(t::string()) )), t::union( t::key('text', t::string()), t::key('content', t::struct( t::key('title', t::string(255)), t::key✱('annotation', t::string(65535)), t::key('text', t::string()), t::key✱('pages', t::cardinal?(5000)) )) ), t::key('status', t::enum('WILL_READ', 'READ', 'FAVORITE_BOOK')) )); echo "Processing input. \n"; if (PHP_SAPI === 'cli') < $input = []; parse_str(implode('&', array_slice($argv, 1)), $input); >else < $input = $_GET; >foreach ($input as $key => $value) < echo "$key: " . json_encode($value) . "\n"; >echo "Validation: " . (t::is($input, t::type(input_t)) ? 'success' : 'failed') . PHP_EOL;

      Этот код проверяет корректность переданного описания элемента книжной серии:

      • Обязательный параметр name должен быть строкой произвольной длины.
      • Обязательный параметр authors должен быть строкой произвольной длины или массивом таких строк.
      • Может быть передан параметр text, являющийся строкой произвольной длины, либо составной параметр content.
      • Обязательный параметр status должен иметь одно из указанных значений.
      name="The Lord of the Rings" authors[]="J. R. R. Tolkien" content[title]="The Return of the King" content[text]=. status=READ

      А такой не пройдёт проверку:

      name="The Lord of the Rings" authors[]="J. R. R. Tolkien" text=. content[title]="The Return of the King" content[text]=. status=READ

      Вместо заключения

      Хотя всё это — в некоторой степени набор велосипедов, но я надеюсь, что он может кому-то пригодиться в работе. typedef может быть удобен для проверки параметров скрипта вместе с их преобразованием с помощью json_decode. А контейнеры могут пригодиться для ограничения типов массивов в аргументах с помощью уже готовых инструментов.

      Можно было бы добавить типизированные свойства объектов, оформить библиотеки в виде расширений для улучшения производительности или сделать ещё что-нибудь необдуманное, но пока я не вижу в этом острой необходимости.

      image

      Так же я буду рад выслушать конструктивную критику и что-то улучшить в этих несложных инструментах или узнать про какой-нибудь silver-bullet, просвистевший мимо меня.

      Благодарю за ваше внимание!

      Источник

      Php создать свой тип данных

      While waiting for native support for typed arrays, here are a couple of alternative ways to ensure strong typing of arrays by abusing variadic functions. The performance of these methods is a mystery to the writer and so the responsibility of benchmarking them falls unto the reader.

      PHP 5.6 added the splat operator (. ) which is used to unpack arrays to be used as function arguments. PHP 7.0 added scalar type hints. Latter versions of PHP have further improved the type system. With these additions and improvements, it is possible to have a decent support for typed arrays.

      function typeArrayNullInt (? int . $arg ): void >

      function doSomething (array $ints ): void (function (? int . $arg ) <>)(. $ints );
      // Alternatively,
      ( fn (? int . $arg ) => $arg )(. $ints );
      // Or to avoid cluttering memory with too many closures
      typeArrayNullInt (. $ints );

      function doSomethingElse (? int . $ints ): void /* . */
      >

      $ints = [ 1 , 2 , 3 , 4 , null ];
      doSomething ( $ints );
      doSomethingElse (. $ints );
      ?>

      Both methods work with all type declarations. The key idea here is to have the functions throw a runtime error if they encounter a typing violation. The typing method used in doSomethingElse is cleaner of the two but it disallows having any other parameters after the variadic parameter. It also requires the call site to be aware of this typing implementation and unpack the array. The method used in doSomething is messier but it does not require the call site to be aware of the typing method as the unpacking is performed within the function. It is also less ambiguous as the doSomethingElse would also accept n individual parameters where as doSomething only accepts an array. doSomething’s method is also easier to strip away if native typed array support is ever added to PHP. Both of these methods only work for input parameters. An array return value type check would need to take place at the call site.

      If strict_types is not enabled, it may be desirable to return the coerced scalar values from the type check function (e.g. floats and strings become integers) to ensure proper typing.

      same data type and same value but first function declare as a argument type declaration and return int(7)
      and second fucntion declare as a return type declaration but return int(8).

      function argument_type_declaration(int $a, int $b) return $a+$b;
      >

      function return_type_declaration($a,$b) :int return $a+$b;
      >

      Источник

      Читайте также:  Add one day to date php
Оцените статью