serafim / properties
PHP属性实现
Requires
- php: ^7.1.3
- psr/simple-cache: ~1.0
- railt/lexer: 1.2.*
- railt/parser: 1.2.*
Requires (Dev)
- phpunit/phpunit: ~7.0
- predis/predis: ^1.1
- railt/compiler: 1.2.*
- symfony/cache: 4.1.*
- symfony/console: 4.1.*
- symfony/var-dumper: 4.1.*
README
基于getter或setter方法以及使用PSR-5 PHPDoc信息的PHP属性实现。
安装
composer require serafim/properties
简介
属性提供控制从对象字段设置和获取数据行为的能力。
在语言级别上没有属性,但可以通过一些附加功能实现。
例如
class MyClass { protected $a = 23; public function __get($field) { return $this->$field; } } $dto = new MyClass(); echo $dto->a; // 23 $dto->a = 42; // Cannot access protected property MyClass::$a
此代码示例未提供类型提示和自动完成。使用无法控制它的魔术方法总是一个糟糕的选择...嗯,看起来很糟糕 %)
我们可以使用PSR-5来修复一些问题。在这种情况下,我们可以添加一个文档块。
/** * @property-read int $a */ class MyClass { // ...
但这个文档块只为IDE添加了信息,不会影响代码本身。同时,你应该始终保持其最新状态。
但是等等!我们还有另一个问题。
$dto = new MyClass(); echo isset($dto->a); // false
这显然是一个错误。我们仍然需要添加__isset
、__unset
和__set
的支持。
太糟糕了!!111
属性使用
现在让我们看看serafim/properties
包提供了什么。
/** * @property $a */ class MyClass { use Serafim\Properties\Properties; protected $a = 23; } $dto = new MyClass(); $dto->a; // 23 $dto->a = 42; // Ok $dto->a; // 42
只读属性
要表示类型应该是只读的,使用@property-read
注解。
/** * @property-read $a */ class MyClass { use Serafim\Properties\Properties; protected $a = 23; } $dto = new MyClass(); $dto->a; // 23 $dto->a = 42; // Error: Property MyClass::$a is readonly
只写属性
要表示类型应该是只读的,使用@property-write
注解。
/** * @property-write $a */ class MyClass { use Serafim\Properties\Properties; protected $a = 23; } $dto = new MyClass(); $dto->a = 42; // 42 $dto->a; // Error: Property MyClass::$a is writeonly
获取器和设置器
对于获取器或设置器重写,只需声明get[Property]
(对于bool
值,使用is[Property]
也是可行的)或set[Property]
方法。
/** * @property-read int $a */ class MyClass { use Serafim\Properties\Properties; protected $a = 23; protected function getA() { return $this->a + 19; } } $dto = new MyClass(); echo $dto->a; // 42 (because 23 + 19 = 42) $dto->a = 42; // Error: Property is read-only (@property-read doc declaration)
设置器
/** * @property-write string $anotherProperty */ class Some { // ... protected $anotherProperty = 'some'; /** * @param string $newVal */ public function setAnotherProperty($newVal) { // Just example if (mb_strlen($newVal) > 4) { throw new InvalidArgumentException('...'); } $this->anotherProperty = $newVal; } }
自动完成
所有这些注解在IDE中完全有效,包括自动完成和高亮显示错误行为。
类型提示
所有具有可写行为的属性都将“可类型检查”。
/** * @property int|null $a */ class Some { use Serafim\Properties\Properties; protected $a; } // $some = new Some; $some->a = 23; // Ok $some->a = null; // Ok $some->a = 'string'; // Error: "TypeError: Value for property Some::$a must be of the type int|null, string given"
原始类型提示
int
(或integer
)- 属性值是整数bool
(或boolean
)- 值是布尔值float
(或double
)- 值是浮点数string
- 值是字符串或具有__toString
方法的对象null
(或void
)- 值是可空的resource
- 值是资源object
- 值可以是任何对象mixed
- 无类型检查callable
- 值可以是字符串、\Closure实例、包含2个参数的数组或具有__invoke
方法的对象scalar
- 值不能是对象countable
- 值可以是可计数的(数组或提供Countable
接口的对象)。self
- 值可以是self类的对象或self类的名称的字符串
self
关键字目前不可用:它将在将来支持
static
- 值可以是self类的实例或子类的实例的字符串
static
关键字目前不可用:它将在将来支持
$this
- 值只能是self类的对象实例
$this
关键字目前不可用:它将在将来支持
数组和泛型
array
- 值是数组类型Class[]
- 值是数组或\Traversable实例scalar[]
- 值类型为数组或\Traversable的实例Collection<>
- 值类型为数组或"Collection"及\Traversable的实例Collection<T>
- 值类型为数组或"Collection"及\Traversable的实例Collection<T,V>
- 值类型为数组或"Collection"及\Traversable的实例
合取与析取
a|b
- 表示值必须是类型(a 或 b)
。a&b
- 表示值必须是类型(a 且 b)
。a|b&c
- 表示值必须是类型(a 或 (b 且 c))
。
更多信息: https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types
生产模式
代码相当高效,但在生产模式下,您应使用缓存。该包实现了对PSR-16标准的支持。
$driver = new Psr16CacheDriver(); // Your PSR16 cache driver implementation $properties = Serafim\Properties\Bootstrap::getInstance(); $properties->setCacheDriver($driver);