在PHP 7中输入属性的提示?

时间:2016-05-16 13:07:58

标签: php attributes php-7 type-hinting variable-types

php 7是否支持类属性的类型提示?

我的意思是,不仅仅是 setters / getters ,而是属性本身。

类似的东西:

class Foo {
    /**
     *
     * @var Bar
     */
    public $bar : Bar;
}

$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error

4 个答案:

答案 0 :(得分:92)

PHP 7.4 will support typed properties如下:

class Person
{
    public string $name;
    public DateTimeImmutable $dateOfBirth;
}

PHP 7.3及更早版本不支持此功能,但有一些替代方案。

您可以创建一个私有属性,只能通过具有类型声明的getter和setter访问:

class Person
{
    private $name;
    public function getName(): string {
        return $this->name;
    }
    public function setName(string $newName) {
        $this->name = $newName;
    }
}

您还可以创建公共属性并使用docblock为阅读代码和使用IDE的人员提供类型信息,但这不提供运行时类型检查:

class Person
{
    /**
      * @var string
      */
    public $name;
}

实际上,您可以组合使用getter和setter以及docblock。

如果您更喜欢冒险,可以使用__get, __set, __isset and __unset magic methods制作虚假财产,并自行检查类型。不过,我不确定我是否会推荐它。

答案 1 :(得分:4)

7.4 +:

好消息,正如@Andrea指出的那样,它将在新版本中实现。 如果有人想在7.4之前使用它,我将在此处保留此解决方案。


7.3以下

基于我仍然从该线程中收到的通知,我相信那里的很多人都遇到过/正在遇到与我相同的问题。对于这种情况,我的解决方案是在特征中结合使用 setters + __set魔术方法,以模拟这种行为。 在这里:

trait SettersTrait
{
    /**
     * @param $name
     * @param $value
     */
    public function __set($name, $value)
    {
        $setter = 'set'.$name;
        if (method_exists($this, $setter)) {
            $this->$setter($value);
        } else {
            $this->$name = $value;
        }
    }
}

这是演示:

class Bar {}
class NotBar {}

class Foo
{
    use SettersTrait; //It could be implemented within this class but I used it as a trait for more flexibility

    /**
     *
     * @var Bar
     */
    private $bar;

    /**
     * @param Bar $bar
     */
    protected function setBar(Bar $bar)
    {
        //(optional) Protected so it wont be called directly by external 'entities'
        $this->bar = $bar;
    }
}

$foo = new Foo();
$foo->bar = new NotBar(); //Error
//$foo->bar = new Bar(); //Success

说明

首先,将bar定义为私有属性,以便PHP将自动__set投射。

__set将检查当前对象(method_exists($this, $setter))中是否声明了某些设置方法。否则,它将仅照常设置其值。

声明一个接收有类型提示参数(setBar(Bar $bar))的setter方法(setBar)。

只要PHP检测到某个非Bar实例的东西正在传递给setter,它将自动触发致命错误: Uncaught TypeError:Argument 1传递给Foo :: setBar()必须是Bar的实例,给定的NotBar的实例

答案 2 :(得分:1)

实际上是不可能的,您只有4种方法来进行实际模拟:

  • 默认值
  • 评论块中的装饰器
  • 构造函数中的默认值
  • 字母和二传手

我将所有这些都合并在这里

spring.jpa.properties.hibernate.jdbc.batch_size = 100
spring.jpa.properties.hibernate.order_inserts   = true 
spring.jpa.properties.hibernate.order_updates   = true

请注意,实际上,您可以将返回值键入?Bar,因为php 7.1(可为空),因为它可能为null(在php7.0中不可用。)

从php7.1开始,您还可以将返回值键入void

答案 3 :(得分:0)

您可以使用setter

ConsumerEndpointFactoryBean

输出:

class Bar {
    public $val;
}

class Foo {
    /**
     *
     * @var Bar
     */
    private $bar;

    /**
     * @return Bar
     */
    public function getBar()
    {
        return $this->bar;
    }

    /**
     * @param Bar $bar
     */
    public function setBar(Bar $bar)
    {
        $this->bar = $bar;
    }

}

$fooInstance = new Foo();
// $fooInstance->bar = new NotBar(); //Error
$fooInstance->setBar($fooInstance);