serafim/properties

PHP属性实现

2.0.1 2018-11-22 13:45 UTC

This package is auto-updated.

Last update: 2024-09-07 15:28:12 UTC


README

Travis CI Scrutinizer CI Latest Stable Version Latest Unstable Version License MIT Total Downloads

基于getter或setter方法以及使用PSR-5 PHPDoc信息的PHP属性实现。

安装

composer require serafim/properties

packagist.org上的包

简介

属性提供控制从对象字段设置和获取数据行为的能力。

在语言级别上没有属性,但可以通过一些附加功能实现。

例如

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中完全有效,包括自动完成和高亮显示错误行为。

IDE Autocomplete And Highlighting

类型提示

所有具有可写行为的属性都将“可类型检查”。

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