TL;DR 不直接,不。 PHP 不是严格类型的。但是,在函数参数或类属性的上下文中,有一些解决方法可能对您有用。
长答案: PHP 不是严格类型的语言,而是松散类型的语言。你可以给一个变量任何你想要的值,不管它是如何初始化的。因此,您不能简单地键入 int $myVar 之类的内容并期望 $myVar = "foo"; 抛出错误。但是 PHP 确实提供了一些方便的功能,让您在处理类的函数参数或属性时达到同样的目的。
选项 1:输入提示
您可以将"type hint" 用于函数参数:
class SomeClass
{
/* code here */
}
function foo(SomeClass $data)
{
/* code here */
}
foo() 将只接受 SomeClass 类型的参数。传递它,比如说,int 将引发致命错误。如果参数是基本类型,如int、string 等,这在 PHP function foo(int $data) {...}。也就是说,有一些库试图以牺牲一点速度为代价来强制它工作。另外,PHP 7 对这类东西增加了很多支持,基于 PHP 的 Hack 语言也是如此。
优点:
缺点:
选项 2:Getter 和 Setter
您也可以使用 getter 和 setter,如下所示:
class SomeClass
{
private $foo = 0;
function setFoo($val = 0)
{
// force it to be an int
if (is_integer($val) {
$this->foo = $val;
} else {
// throw an error, raise an exception, or otherwise respond
}
}
}
优点:
缺点:
- 仅适用于程序定义的类
- 不适用于基本类型
- 需要大量代码
选项 3:魔术方法
这个方法是我最喜欢的,也是最复杂的。使用__set() magic method 处理类属性。
class MyClass {
private $type = 0; // we will force this to be an int
private $string = ''; // we will force this to be a string
private $arr = array(); // we will force this to be an array
private $percent = 0; // we will force this to be a float in the range 0..100
function __set($name, $value) {
switch ($name) {
case "type":
$valid = is_integer($value);
break;
case "string":
$valid = is_string($value);
break;
case "arr":
$valid = is_array($value);
break;
case "percent":
$valid = is_float($value) && $value >= 0 && $value <= 100;
break;
default:
$valid = true; // allow all other attempts to set values (or make this false to deny them)
}
if ($valid) {
$this->{$name} = $value;
// just for demonstration
echo "pass: Set \$this->$name = ";
var_dump($value);
} else {
// throw an error, raise an exception, or otherwise respond
// just for demonstration
echo "FAIL: Cannot set \$this->$name = ";
var_dump($value);
}
}
}
$myObject = new MyClass();
$myObject->type = 1; // okay
$myObject->type = "123"; // fail
$myObject->string = 1; // fail
$myObject->string = "123"; // okay
$myObject->arr = 1; // fail
$myObject->arr = "123"; // fail
$myObject->arr = array("123"); // okay
$myObject->percent = 25.6; // okay
$myObject->percent = "123"; // fail
$myObject->percent = array("123"); // fail
$myObject->percent = 123456; // fail
优点:
缺点:
- 仅适用于程序定义的类
- 不适用于基本类型
- 需要大量
switching 或 if/else 逻辑
- 可能会导致 IDE 无法正确自动完成属性类型的问题
这是demo of this approach。
结束思想
最后,如果您使用的是 PHPStorm 之类的 IDE,请不要忘记 PHPDoc 类型提示:
/* @var integer */
$foo = 0; // will result in warnings if the IDE is configured properly and you try to do something like substr($foo, 1, 4);
如果您真的想要成为硬核,您可以使用Hack 进行强类型化,但代价是降低您的代码的可移植性和(目前)与主要 IDE 的兼容性。
当然,这些都不能替代显式验证用户输入和彻底测试应用程序对意外输入类型的响应。