PHP类型提示到原始值?


73

我想知道是否有人可以提示一种方法来期望原始类型?

像这样:

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

要么:

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

用同样的方式:

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

这可能在php中吗?


2
在这里输入提示信息,php.net
manual /

10
仅适用于PHP 7
zloctb

或者如果您未使用PHP 7.x,则可以使用NSPL的args模块
Ihor Burlachenko 2016年

Answers:


86

在PHP 7中,他们添加了以下内容:

类型声明允许函数在调用时要求参数为某种类型。如果给定的值类型不正确,则会生成错误:在PHP 5中,这将是可恢复的致命错误,而PHP 7将抛出TypeError异常。

参考:http : //php.net/manual/zh/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


1
好。谢谢。您认为他们将来会随时提供它吗?还是像他们所说的那样“与php哲学兼容”?
费利佩

1
@Felipe,这是PHP团队不关心/根本不希望更改的情况之一,即使现有行为已损坏或不受欢迎。他们的问题跟踪器里塞满了这些东西。有关类型提示的特定问题,请参见我的答案。
拉菲·凯特勒

我不认为PHP希望很快就开始使用类型。为什么要担心类型?
afuzzyllama 2011年

@Rafe Kettler怎么样?根据w3c并非如此。我仍然不知道将变量绑定到某种类型。
afuzzyllama 2011年

21
@afuzzyllama w3schools不是w3c。w3c一直困扰着他们,以防止误导人们以为他们是他们。PHP开发人员声称它是强类型的(这实际上是强类型的唯一要求),但实际上不是。当我评论说它是强类型的时候,我不知道我在想什么。
拉菲·凯特勒


16

是的,现在有可能,经过长时间的讨论,关于标量函数参数和返回值的类型提示实现建议已获批准,到目前为止投票数最高,请查看详细信息:

标量类型提示包括声明函数参数和返回值的类型,这些值可以是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引擎尝试返回值时,它将检查是否与声明的值不匹配,这将引发致命错误,如致命错误:传递给increment()的参数1必须为整数类型,字符串为给定

借助声明的这一新功能,您可以通过检测由于将错误类型的值传递给函数而导致的早期编程错误来编写更强大的应用程序。

类型的自动更改也可能发生。例如,可以将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");

弱类型检查和类型转换的行为:弱类型检查模式可以与声明clarify(strict_types = 0)一起使用;或没有严格类型声明。需要考虑以下几点:对扩展或内置PHP函数的弱类型检查调用与以前的PHP版本具有相同的行为新标量类型声明的弱类型检查规则与扩展或内置PHP函数。NULL是一种特殊情况,目的是与类,可调用对象和数组的当前类型声明保持一致。缺省情况下,不接受NULL,除非它是一个参数并且显式指定为默认值NULL,例如:function sample(int $ a = NULL);

这种方法有很多优点。您将获得类型安全性。这意味着您最终可以静态分析代码!您可以检测到错误地从一个函数中获取字符串并将其作为整数传递给另一个函数的错误。对于我来说,每天使用PHP并将Java作为OOP语言参考的开发人员来说,这对PHP来说是一个巨大的进步。


这不是Hack而不是PHP?
费利佩2015年

这是真的吗?我们可以期望这些功能在哪个版本上发布?
robbmj

仅供参考...除非存在具有该名称的类或接口,否则不存在数字类型。
DigiLive

6

每个人都已经说过了,因为PHP不支持原语,所以您不能为原语键入提示。其背后的原因不仅与自动转换有关,还与社区反应有关。

到目前为止,我还记得2010年5月在PHP主干中添加了对标量类型提示的支持。但是由于社区的反馈,此功能并未纳入5.4版本。

对此存在一些争议。反对更改的人认为,这种支持将与PHP的基本设计背道而驰。PHP被认为是一种弱类型语言。从本质上讲,这意味着PHP不需要声明数据类型。变量仍然具有与之关联的数据类型,但是您可以做一些根本性的事情,例如将字符串添加到整数而不会导致错误。

恕我直言:标量类型提示应该尽快添加到PHP中,这是我们所有人都需要的功能,我非常尊重PHP是弱类型语言,但是对于高端开发和生产,尤其是在OO上下文中,标量类型提示是必须具备的。像过程和OO一样,我们在PHP中可以有两种选择。


3

对的,这是可能的。

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

警告:有在原来的手工输入错误:RES RO UCE,而不是资源OU RCE

人们经常问标量/基本类型提示。这是我在MVC框架中使用的一类类,该类将通过使用自定义错误处理程序来启用类型提示。

注意:您应将此代码放在包含头文件中的所有其他代码之上,并且如果您使用的是set_error_handler()函数,则应注意它也会使用它。您可能需要链接set_error_handlers()

为什么?

  1. 因为人们讨厌使用is_ *函数来验证参数。
  2. 减少防御性编码器的冗余编码。
  3. 函数/方法是自定义的/有关所需输入的文档。

另外,请按照PHP Internals板上有关PHP 6.0中类型提示的讨论进行操作。

<?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

根据PHP文档基本类型不支持类型提示。

不过,它支持类和接口。

编辑:我忘了提到数组也支持。


嗯..我不认为它不支持接口...还是我错了?
费利佩

1
我这样做的接口。然后,我很确定你是错的:-)
Luc M

嗯...前段时间我问了同样的问题。.我得到的一般印象是行不通的...在这里看stackoverflow.com/questions/5346393/…–
Felipe

我必须对我的代码做一些测试...我有MyMethod(iMyInterface $ some_interface)之类的方法...而且,如果我通过了一些未实现iMyInterface接口的东西,它就不会“编译”。但是我没有尝试传递一个带有要实现的方法名称的类,而无需实现接口。
卢克M

0

这是用于从传入参数中强制布尔值的简短语法。如果$state为true,则$this->is_active设置为true。对于所有其他类型的值,将其设置为false。

function set_active ( $state ) {
    $this->is_active = true === $state;
}

-3

我猜您不需要PHP的类型提示,因为您已经获得了类型检查功能,例如is_bool(),is_string()等,因此您可以在实际制作任何类型的参数之前对其进行检查一个参数,尽管他们用来检查数组和对象类型的方法要干净得多。


5
类型提示将防止不必要if(!is_bool($bool)) throw new InvalidTypeException('Arg $bool must be a boolean');的每个函数中的每个参数。在设计固态API时,我总是键入检查我的参数。而且类型提示会节省很多if语句...我不知道所有这些if语句怎么可能cleaner...
AlexMorley-Finch 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.