PHP намекает на примитивные значения? - PullRequest
72 голосов
/ 20 апреля 2011

Я хотел бы знать, можно ли намекнуть на тип метода, ожидающего примитивные типы?

Примерно так:

public function someMethod(string $str)
                         //^^^^^^

Или:

private function anotherMethod(int $num)
                             //^^^

так же, как вы бы:

private function otherMethod(Person $rambo)
                           //^^^^^^

Возможно ли это в php?

Ответы [ 8 ]

83 голосов
/ 20 апреля 2011

В PHP 7 они добавили следующее:

Объявления типов позволяют функциям требовать, чтобы параметры имели определенный тип во время вызова.Если заданное значение имеет неправильный тип, то генерируется ошибка: в PHP 5 это будет исправимая фатальная ошибка, а PHP 7 вызовет исключение TypeError.

Ссылка: http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration


Когда был задан этот ответ, PHP 5 был последним и сказал следующее:

PHP 5 вводит подсказку типа.Теперь функции могут заставить параметры быть объектами (указав имя класса в прототипе функции), интерфейсами, массивами (начиная с PHP 5.1) или вызываться (начиная с PHP 5.4) .Однако если в качестве значения параметра по умолчанию используется NULL, он будет разрешен в качестве аргумента для любого последующего вызова.

Если в качестве подсказки типа указан класс или интерфейс, то разрешены также все его дочерние элементы или реализации.

Типовые подсказки нельзя использовать со скалярными типами, такими как int или string. Ресурсы и черты также недопустимы.

Ссылка: http://php.net/manual/en/language.oop5.typehinting.php

29 голосов
/ 20 апреля 2011

Неа. Вы не можете напечатать подсказку для примитивов, потому что PHP имеет автоматические преобразования для примитивов. См. http://bugs.php.net/bug.php?id=29508. Это никогда не изменится, если у команды PHP внезапное изменение мнения (что сомнительно, они довольно упрямы).

16 голосов
/ 23 марта 2015

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

Подсказка скалярного типа состоит из объявления типов параметров функции и возвращаемых значений, которые могут быть типов int, float, string и bool. Это позволяет движку PHP времени выполнения проверять, переданы ли типы значений функциям параметров, и возвращать значения имеют ожидаемые типы для обнаружения возможных ошибок программирования. Подсказки типов для объектов, массивов и вызываемых объектов уже разрешались в прошлых версиях PHP. Текущая реализация представляет пять новых зарезервированных слов: int, float, bool, string и numeric. Они не были ранее зарезервированы, потому что приведение - это особый случай в лексере.

Example :
function test(float $a) {
    var_dump($a); 
}

test(1); // float(1)
test("1"); // float(1)
test(1.0); // float(1)
test("1a"); // E_RECOVERABLE_ERROR
test("a"); // E_RECOVERABLE_ERROR
test(""); // E_RECOVERABLE_ERROR
test(1.5); // float(1.5)
test(array()); // E_RECOVERABLE_ERROR
test(new StdClass); // E_RECOVERABLE_ERROR

У вас также есть возможность объявить в исходном файле, где вы можете разрешить хинтинг типа Scaler. Он должен быть первой строкой вашего скрипта конфигурации и не может быть объявлен в другом месте в том же файле.

Like : declare(strict_types=1);

Во время выполнения, когда механизм PHP пытается вернуть значение, он проверит, не совпадает ли заявленное, и выдаст фатальную ошибку, например, Неустранимая ошибка: аргумент 1, передаваемый в increment (), должен иметь тип integer, строка:

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

Также могут происходить автоматические изменения типов. Например, типы int могут автоматически изменяться на параметры типа float,

function test(float $x){
    var_dump($x);
}
test(10); // works fine

Объявление типа возврата

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

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

function mustReturnInt(): int { ... }
function mustReturnString(): string { ... }
function mustReturnBool(): bool { ... }
function mustReturnFloat(): float { ... }
function doesNotReturnAnything() { ... }

Немного более сложный пример

declare(strict_types=1);  
class StrictTypesTestingClass {  
public function returnSameInt(int $value): int {   return $value;  }   
public function returnSameFloat(float $value): float {   return $value;  }  
public function returnSameString(string $value): string {   return $value;  }   
public function returnSameBool(bool $value): bool {   return $value;  } }  
$check = new StrictTypesTestingClass();  // calls that work  print $check->returnSameInt(10); 
print $check->returnSameFloat(10.0); 
print $check->returnSameString("test"); 
print $check->returnSameBool(true) ? 'true' : 'false';  // calls that throw exceptions 
print $check->returnSameInt("10"); 
print $check->returnSameFloat("10.0"); 
print $check->returnSameString(10);
print $check->returnSameBool("true");

Поведение при слабой проверке типов и преобразовании типов: режим слабой проверки типов можно использовать с оператором Declare (strict_types = 0); или отсутствие строгой декларации типов. Есть несколько моментов, которые необходимо учитывать: Слабый тип проверенных вызовов к расширению или встроенной функции PHP имеет такое же поведение, как и в предыдущих версиях PHP Правила слабой проверки типов для новых объявлений скалярных типов в основном такие же, как и для расширенных или встроенных функций PHP. NULL является особым случаем, чтобы соответствовать текущим объявлениям типов для классов, вызываемых и массивов. NULL не принимается по умолчанию, если только он не является параметром и ему явно задано значение по умолчанию NULL, например: функция sample (int $ a = NULL);

У этого подхода много преимуществ. Вы получаете безопасность типа. А это значит, что вы наконец-то можете статически анализировать код! Вы можете обнаружить ошибки, когда вы случайно взяли строку из одной функции и передали ее как целое число в другую. Для меня, разработчика, который ежедневно использует PHP и рассматривает Java как ссылку для языков ООП, это большой прогресс для PHP .

5 голосов
/ 27 декабря 2013

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

Пока я могу вспомнить, что в мае 2010 года в хобот PHP была добавлена ​​поддержка хинтинга скалярного типа. Но из-за реакции сообщества эта функция не появилась в версии 5.4.

Был небольшой спор об этом. Те, кто выступал против изменений, утверждали, что эта поддержка будет идти вразрез с основами PHP. PHP считается слабым типизированным языком. По сути, это означает, что PHP не требует, чтобы вы объявляли типы данных. С переменными по-прежнему связаны типы данных, но вы можете делать радикальные вещи, такие как добавление строки к целому числу, не приводя к ошибке.

ИМХО: Подсказка скалярного типа должна быть добавлена ​​в PHP как можно скорее, это особенность, которая нам всем нужна, я действительно уважаю, что PHP - это язык со слабым типом, но для высокопроизводительной разработки и производства, особенно в контексте OO , хинтинг скалярного типа является обязательным условием. У нас могут быть обе альтернативы в PHP, как процедурные, так и OO.

3 голосов
/ 12 июля 2015

Да, это возможно.

http://ru2.php.net/manual/ru/language.oop5.typehinting.php#83442

Предупреждение: в оригинальной инструкции есть опечатка: вместо * res ro uceof res ou rce

Люди часто спрашивают о скалярных / базовых печатных текстах.Вот капля в классе, которую я использую в своей инфраструктуре MVC, которая позволит использовать печатные шрифты с помощью пользовательского обработчика ошибок.

Примечание. Этот код следует включать над всем другим кодом в заголовки включаемых файлов, а если выесли вы используете функцию set_error_handler (), вы должны знать, что она также использует ее.Возможно, вам понадобится связать вашу set_error_handlers ()

Почему?

  1. Поскольку людям надоело использовать функции is_ * для проверки параметров.
  2. Сокращение избыточного кодированиядля защитников
  3. Функции / методы самоопределяются / документируются в соответствии с требуемым вводом.

Также .. Следуйте обсуждению для ввода шрифтов в PHP 6.0 на платах PHP Internals.

<?php

define('TYPEHINT_PCRE', '/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/');

class Typehint
{

    private static $Typehints = array(
        'boolean'   => 'is_bool',
        'integer'   => 'is_int',
        'float'     => 'is_float',
        'string'    => 'is_string',
        'resource'  => 'is_resource'
    );

    private function __Constrct() {}

    public static function initializeHandler()
    {

        set_error_handler('Typehint::handleTypehint');

        return TRUE;
    }

    private static function getTypehintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, &$ThArgValue)
    {

        foreach ($ThBackTrace as $ThTrace)
        {

            // Match the function; Note we could do more defensive error checking.
            if (isset($ThTrace['function']) && $ThTrace['function'] == $ThFunction)
            {

                $ThArgValue = $ThTrace['args'][$ThArgIndex - 1];

                return TRUE;
            }
        }

        return FALSE;
    }

    public static function handleTypehint($ErrLevel, $ErrMessage)
    {

        if ($ErrLevel == E_RECOVERABLE_ERROR)
        {

            if (preg_match(TYPEHINT_PCRE, $ErrMessage, $ErrMatches))
            {

                list($ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType) = $ErrMatches;

                if (isset(self::$Typehints[$ThHint]))
                {

                    $ThBacktrace = debug_backtrace();
                    $ThArgValue  = NULL;

                    if (self::getTypehintedArgument($ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue))
                    {

                        if (call_user_func(self::$Typehints[$ThHint], $ThArgValue))
                        {

                            return TRUE;
                        }
                    }
                }
            }
        }

        return FALSE;
    }
}

Typehint::initializeHandler();

?>

An are some examples of the class in use:

<?php

function teststring(string $string) { echo $string; }
function testinteger(integer $integer) { echo $integer; }
function testfloat(float $float) { echo $float; }

// This will work for class methods as well.

?>

Вы получите картинку ..

1 голос
/ 20 апреля 2011

Соответствует документации PHP подсказка типов не поддерживается для примитивных типов.

Хотя поддерживается для классов и интерфейсов.

Редактировать: я забыл упомянуть, что это также поддерживается для массивов.

0 голосов
/ 22 мая 2015

Вот краткий синтаксис для вытеснения логического значения из переданного параметра.Если $state равно true, тогда $this->is_active установлено в значение true.Для всех других типов значений установлено значение false.

function set_active ( $state ) {
    $this->is_active = true === $state;
}
0 голосов
/ 18 июля 2011

Полагаю, вам не нужен хинтинг типов для PHP, потому что вы получили функции проверки типов, такие как is_bool (), is_string () и т. Д., Так что вы можете проверить все, что пытаетесь вставить в аргумент против этих функций, прежде чем фактически делая это аргументом, хотя метод, который они используют для проверки массивов и типов объектов, был бы намного чище.

...