PHP 中的属性类型提示 7?
Type hinting for properties in PHP 7?
php 7 是否支持 class 属性的类型提示?
我的意思是,不只是为了 setters/getters,而是为了 属性 本身。
类似于:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
您可以使用setter
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);
输出:
TypeError: Argument 1 passed to Foo::setBar() must be an instance of Bar, instance of Foo given, called in ...
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;
}
}
您还可以制作 public 属性 并使用文档块向阅读代码和使用 IDE 的人提供类型信息,但这不提供运行时类型检查:
class Person
{
/**
* @var string
*/
public $name;
}
事实上,您可以将 getter 和 setter 与文档块结合起来。
如果你更喜欢冒险,你可以用 __get
, __set
, __isset
and __unset
magic methods 制作一个假的 属性,然后自己检查类型。不过,我不确定我是否会推荐它。
7.4+:
正如@Andrea 指出的那样,好消息是它将在新版本中实现。
我将把这个解决方案留在这里,以防有人想在 7.4
之前使用它
7.3以下
根据我仍然从该线程收到的通知,我相信那里的许多人 had/is 遇到了与我相同的问题。我对这种情况的解决方案是在特征中组合 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)
) 中是否声明了某些 setter。否则它只会像往常一样设置它的值。
声明接收类型提示参数 (setBar(Bar $bar)
) 的 setter 方法 (setBar)。
只要 PHP 检测到某些不是 Bar
实例的东西正在传递给 setter,它就会自动触发致命错误:未捕获TypeError:传递给 Foo::setBar() 的参数 1 必须是 Bar 的实例,给定的 NotBar 实例
编辑 PHP 7.4 :
从 PHP 7.4 开始,您可以键入属性 (Documentation / Wiki),这意味着您可以:
class Foo
{
protected ?Bar $bar;
public int $id;
...
}
根据 wiki,所有可接受的值是:
- bool, int, float, string, array, object
- 可迭代
- 自己,parent
- 任何class或接口名称
- ?type // 其中“type”可以是以上任何一种
PHP < 7.4
这实际上是不可能的,您只有 4 种方法可以实际模拟它:
- 默认值
- 评论区中的装饰器
- 构造函数中的默认值
- getter 和 setter
我把它们全部合并在这里
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;
}
}
请注意,自 php 7.1(可为空)以来,您实际上可以将 return 键入为 ?Bar,因为它可能为空(在 php7.0 中不可用。)
您还可以将 return 键入为 void,因为 php7.1
php 7 是否支持 class 属性的类型提示?
我的意思是,不只是为了 setters/getters,而是为了 属性 本身。
类似于:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
您可以使用setter
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);
输出:
TypeError: Argument 1 passed to Foo::setBar() must be an instance of Bar, instance of Foo given, called in ...
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;
}
}
您还可以制作 public 属性 并使用文档块向阅读代码和使用 IDE 的人提供类型信息,但这不提供运行时类型检查:
class Person
{
/**
* @var string
*/
public $name;
}
事实上,您可以将 getter 和 setter 与文档块结合起来。
如果你更喜欢冒险,你可以用 __get
, __set
, __isset
and __unset
magic methods 制作一个假的 属性,然后自己检查类型。不过,我不确定我是否会推荐它。
7.4+:
正如@Andrea 指出的那样,好消息是它将在新版本中实现。 我将把这个解决方案留在这里,以防有人想在 7.4
之前使用它7.3以下
根据我仍然从该线程收到的通知,我相信那里的许多人 had/is 遇到了与我相同的问题。我对这种情况的解决方案是在特征中组合 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)
) 中是否声明了某些 setter。否则它只会像往常一样设置它的值。
声明接收类型提示参数 (setBar(Bar $bar)
) 的 setter 方法 (setBar)。
只要 PHP 检测到某些不是 Bar
实例的东西正在传递给 setter,它就会自动触发致命错误:未捕获TypeError:传递给 Foo::setBar() 的参数 1 必须是 Bar 的实例,给定的 NotBar 实例
编辑 PHP 7.4 :
从 PHP 7.4 开始,您可以键入属性 (Documentation / Wiki),这意味着您可以:
class Foo
{
protected ?Bar $bar;
public int $id;
...
}
根据 wiki,所有可接受的值是:
- bool, int, float, string, array, object
- 可迭代
- 自己,parent
- 任何class或接口名称
- ?type // 其中“type”可以是以上任何一种
PHP < 7.4
这实际上是不可能的,您只有 4 种方法可以实际模拟它:
- 默认值
- 评论区中的装饰器
- 构造函数中的默认值
- getter 和 setter
我把它们全部合并在这里
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;
}
}
请注意,自 php 7.1(可为空)以来,您实际上可以将 return 键入为 ?Bar,因为它可能为空(在 php7.0 中不可用。)
您还可以将 return 键入为 void,因为 php7.1