Can We Restrict PHP Variables to accept only certain type of values

后端 未结 3 1245
深忆病人
深忆病人 2021-01-03 08:23

i am wondering is it possible to restrict php variable to accept only certain type of variable it is defined to accept.

e-g if we see in C#

public in         


        
相关标签:
3条回答
  • 2021-01-03 08:38

    You have to made it by your own hands, example :

    function setInt(&$var, $value) {
        if(!is_integer($value) {
            throw new Exception("Integer wanted " . gettype($value) . " received");
        }
        $var = $value;
    }
    
    0 讨论(0)
  • 2021-01-03 08:59

    TL;DR Not directly, no. PHP is not strictly-typed. There are, however, a few workarounds that may work for you in the context of function parameters or properties of classes.

    Long answer: PHP is not a strictly-typed language, but loosely-typed. You can give a variable any value you want, regardless of how it was initialized. So, you can't simply type something like int $myVar and expect $myVar = "foo"; to throw an error. But PHP does offer a few handy features to get you to the same end when dealing with function parameters or properties of a class.

    Option 1: Type hints

    You can use a "type hint" for function parameters:

    class SomeClass 
    {
        /* code here */
    }
    
    function foo(SomeClass $data)
    {
        /* code here */
    }
    

    foo() will only accept parameters of type SomeClass. Passing it, say, an int will throw a fatal error. This doesn't work in PHP < 7 if the parameters are intended to be base types, like int, string, etc., so you can't do function foo(int $data) {...}. That said, there are a few libraries out there that attempt to force it to work at the expense of a little speed. Also, PHP 7 adds a lot of support for this kind of thing, as does the Hack language based on PHP.

    Pros:

    • Easy
    • Intuitive

    Cons:

    • Only works for program-defined classes
    • Unavailable for base types

    Option 2: Getters and Setters

    You can also use getters and setters, like so:

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

    Pros:

    • Relatively easy
    • Relatively intuitive

    Cons:

    • Only works in program-defined classes
    • Unavailable for base types
    • Requires lots of code

    Option 3: Magic Methods

    This method is my favorite, but also the most complicated. Use the __set() magic method to deal with class properties.

    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
    

    Pros:

    • Relatively easy
    • Intuitive
    • Extremely powerful: one setter to rule them all

    Cons:

    • Only works in program-defined classes
    • Unavailable for base types
    • Requires lots of switching or if/else logic
    • Can cause problems with IDEs not auto-completing property types correctly

    Here's a demo of this approach.

    Closing Thoughts

    Finally, if you're using an IDE like PHPStorm, don't forget about PHPDoc type hints:

    /* @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);
    

    And if you really want to go hard core, you can do strong typing using Hack, at the expense of making your code less portable and less compatible (for now) with major IDEs.

    Of course, none of these is a substitute for explicitly validating user input and thoroughly testing the application's response to unexpected input types.

    0 讨论(0)
  • 2021-01-03 08:59

    No. PHP is not a strictly typed language. You can however use type hints in functions and methods.

    If class or interface is specified as type hint then all its children or implementations are allowed too.

    Type hints can not be used with scalar types such as int or string. Resources and Traits are not allowed either.

    The Scalar types being:

    • string
    • bool
    • int
    • float

    Examples:

    function (array $theArr) {
      // body
    }
    
    class X {
      public function __construct(SomeOtherClass $arg) {
        // body
      }
    
      public function setFoo(Foo $foo) {
    
      }
    }
    

    See the manual for more specifics: http://php.net/manual/en/language.oop5.typehinting.php

    0 讨论(0)
提交回复
热议问题