我们可以限制PHP变量以仅接受某些类型的值

时间:2014-12-31 13:07:30

标签: php

我想知道是否可以限制php变量只接受它定义为接受的某种类型的变量。

如果我们在C#中看到的话,请注意

public int variable = 20;
public string variable2 = "Hello World";

那么如果我想限制变量的类型,那会是什么样的。

public int $variable = 20;

因此,如果我尝试将字符串分配给整数变量,我会得到错误。

public int $varaible = "Hello World"; //As type is integer, it should throw error.

是否有这样的事情在PHP中为变量定义类型之前为它赋值?

3 个答案:

答案 0 :(得分:9)

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会引发一个致命的错误。这不适用于PHP< 7如果参数是基本类型,如intstring等,那么您无法执行function foo(int $data) {...}。也就是说,有一些库试图以牺牲一点速度为代价来强制它运行。此外,PHP 7为基于PHP的Hack语言添加了很多支持。

<强>优点:

  • 易于
  • 直观

<强>缺点:

  • 仅适用于程序定义的类
  • 基本类型不可用

选项2:获取和设置者

你也可以使用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

<强>优点:

  • 相对容易
  • 直观
  • 非常强大:一个统治者可以统治他们

<强>缺点:

  • 仅适用于程序定义的类
  • 基本类型不可用
  • 需要大量switchif / 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中。

当然,这些都不能替代明确验证用户输入并彻底测试应用程序对意外输入类型的响应。

答案 1 :(得分:4)

没有。 PHP不是严格类型的语言。但是,您可以在函数和方法中使用type hints

  

如果将类或接口指定为类型提示,则也允许其所有子项或实现。

     

类型提示不能与标量类型(如int或string)一起使用。资源和特征也是不允许的。

标量类型为:

  • string
  • bool
  • int
  • float

示例:

function (array $theArr) {
  // body
}

class X {
  public function __construct(SomeOtherClass $arg) {
    // body
  }

  public function setFoo(Foo $foo) {

  }
}

有关详细信息,请参阅手册:http://php.net/manual/en/language.oop5.typehinting.php

答案 2 :(得分:0)

你必须亲自动手,例如:

function setInt(&$var, $value) {
    if(!is_integer($value) {
        throw new Exception("Integer wanted " . gettype($value) . " received");
    }
    $var = $value;
}