Управление Скалярными Типами В Php 5

[Обновлено]: Внес некоторые изменения в код. Спасибо итилион И Одинокий кот Все уже знают, что в PHP 5 в аргументах функций можно указывать их тип, за исключением.

скалярных типов, т. е.

: целочисленного, строкового, логического, плавающего и т. д. Однако на страница руководства По поводу контроля типов в комментариях Дэниел Л.

Вуд предлагает довольно интересное решение этой проблемы с помощью класса-обработчика ошибок.

Единственным существенным недостатком этого решения является его производительность.

Ниже я постараюсь рассказать, как можно оптимизировать это решение и стоит ли его в принципе использовать в продакшен-релизах.

Итак, давайте посмотрим, что не так с приведенным выше решением:

Совершенно ненужные вызовы debug_backtrace. В принципе, анализа сообщения об ошибке достаточно для решения проблемы.

Явная проверка аргументов попахивает паранойей.

Действительно, если мы поймали сообщение типа «Аргумент N, переданный в Class::function(), должен быть экземпляром строки, указана строка, .

» — это уже дает нам все основания сделать правильный выбор.

Примечание .

веревка, веревка .

В случае ошибки будет, например, .

целое число, строка.

Этого достаточно, чтобы определить, является ли данное сообщение на самом деле ошибкой или нет. В массиве типов опечатка.

ты сроу ce' => 'is_resource'.

Несколько неоптимальный код в некоторых местах.

Мы попробуем решить все эти проблемы, переписав класс следующим образом:

 <Эphp
 class Typehint {
 
     private static $_types = array(
         'boolean,'   => 'boolean',
         'bool,'      => 'boolean',
         'integer,'   => 'integer',
         'int,'       => 'integer',
         'float,'     => 'float',
         'double,'    => 'float',
         'real,'      => 'float',
         'string,'    => 'string',
         'resource,'  => 'resource'
     );
 
     private function __construct() {}
 
     public static function init(){
         set_error_handler('Typehint::handle');
         return true;
     }
 
     public static function handle( $lvl, $msg) {
         if ($lvl == E_RECOVERABLE_ERROR && strstr($msg, 'must be an instance of') !== false) {
             $errmsg = explode(' ', $msg, 13);
             return isset( self::$_types[$errmsg[10]]) && self::$_types[$errmsg[10]] == $errmsg[11];
         }
         return false;
     }
 }
 ?>
Давайте теперь проведем несколько тестов и посмотрим, что мы получим.

 <Эphp
 require_once 'Typehint.php';
 Typehint::init();
 
 function teststring( string $string) { return $string; }
 function test( $var) { return $var; }
 
 function micro_time() {
     $timearray = explode(" ", microtime());
     return ($timearray[1] + $timearray[0]);
 }
 $start = micro_time();
 
 for ($i = 0; $i < 10000; $i++) {
     teststring( '123');
 }
 
 $end = micro_time();
 
 echo 'With Typehint: ' .

($end-$start) .

' sec.'; echo "<br />\n"; $start = micro_time(); for ($i = 0; $i < 10000; $i++) { test( '123'); } $end = micro_time(); echo 'Without Typehint: ' .

($end-$start) .

' sec.'; ?>

Вот что я получил: С Typehint: 0,0787329673767 сек.

Без Typehint: 0,00326299667358 сек.

Замечу, что для оригинального решения от Дэниела мой результат составил: 0,215523958206 сек.

Те.

мы выиграли почти в 2,7 раза в производительности.

Однако, как мы видим, без использования решения Typehint мы бы выиграли в производительности более чем в 24 раза.

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

Это говорит о целесообразности его использования.

Посмотрите, 10 000 вызовов добавляют ко времени выполнения скрипта почти 0,1 секунды.

Здесь есть о чем подумать.

С другой стороны, использование Typehint повышает самодокументированность кода и позволяет в некоторых случаях, когда это особенно необходимо, контролировать тип передаваемых аргументов.

Однако следует учитывать, что повсеместная строгая типизация в PHP, по сути, не даст вам никаких преимуществ, т.к.

в языке нет механизма перегрузки; при объявленном типе возникнут проблемы со значениями аргументов по умолчанию.

Кроме того, никто не может гарантировать возвращаемые значения в конструкциях языка.

Поэтому вам следует несколько раз подумать, прежде чем использовать это решение или нет. Если вы все еще видите осуществимость и хотите использовать это в своем проекте, я предлагаю вам рассмотреть возможность/необходимость создания какого-то автоматического сборщика, который выпустит окончательный код для использования в производстве, очистив скалярные типы в определениях функций и методы класса.

В принципе, сделать это будет несложно, хотя бы с помощью того же PHP или Shell. Удачи вам в развитии! P.S. Кросс-пост из моего блога: mikhailstadnik.com/php5-types-control Теги: #php #php 5 #управление типами #ввод #решение #php

Вместе с данным постом часто просматривают: