Car*_*cce 72 php attributes variable-types type-hinting php-7
php 7是否支持类属性的类型提示?
我的意思是,不仅仅是针对建立者/吸气者,而是针对房产本身.
就像是:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
Run Code Online (Sandbox Code Playgroud)
And*_*rea 119
class Person
{
public string $name;
public DateTimeImmutable $dateOfBirth;
}
Run Code Online (Sandbox Code Playgroud)
PHP 7.3及更早版本不支持此功能,但有一些替代方案.
您可以创建一个私有属性,只能通过具有类型声明的getter和setter访问:
class Person
{
private $name;
public function getName(): string {
return $this->name;
}
public function setName(string $newName) {
$this->name = $newName;
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以创建公共属性并使用docblock为读取代码和使用IDE的人员提供类型信息,但这不提供运行时类型检查:
class Person
{
/**
* @var string
*/
public $name;
}
Run Code Online (Sandbox Code Playgroud)
实际上,您可以组合getter和setter以及docblock.
如果你更喜欢冒险,你可以使用假的性质__get,__set,__isset和__unset魔术方法,并检查自己的类型.不过,我不确定我是否会推荐它.
7.4+:
如@Andrea所指出的,好消息是它将在新版本中实现。如果有人想在7.4之前使用它,我将在此处保留此解决方案。
7.3以下
根据我仍然从该线程收到的通知,我相信那里的许多人都遇到过/正在遇到与我相同的问题。对于这种情况,我的解决方案是在特征中结合使用setter和__setmagic方法,以模拟这种行为。这里是:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是演示:
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
Run Code Online (Sandbox Code Playgroud)
说明
首先,将其定义bar为私有属性,以便PHP __set 自动进行铸造。
__set将检查当前对象(method_exists($this, $setter))中是否声明了一些设置器。否则,它将仅照常设置其值。
声明一个接收有类型提示参数(setBar(Bar $bar))的setter方法(setBar )。
只要PHP检测到非Bar实例传递给setter,它将自动触发致命错误:Uncaught TypeError:传递给Foo :: setBar()的参数1必须是Bar的实例,NotBar的实例已给定
为 PHP 7.4 编辑:
从 PHP 7.4 开始,您可以输入属性(文档/维基),这意味着您可以:
class Foo
{
protected ?Bar $bar;
public int $id;
...
}
Run Code Online (Sandbox Code Playgroud)
根据维基,所有可接受的值是:
PHP < 7.4
这实际上是不可能的,你只有 4 种方法来实际模拟它:
我把它们都结合在这里
class Foo
{
/**
* @var Bar
*/
protected $bar = null;
/**
* Foo constructor
* @param Bar $bar
**/
public function __construct(Bar $bar = null){
$this->bar = $bar;
}
/**
* @return Bar
*/
public function getBar() : ?Bar{
return $this->bar;
}
/**
* @param Bar $bar
*/
public function setBar(Bar $bar) {
$this->bar = $bar;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,从 php 7.1 开始,您实际上可以将返回值输入为 ?Bar(可空),因为它可能为 null(在 php7.0 中不可用。)
从 php7.1 开始,您也可以将返回值输入为 void