phpgears / immutability
PHP对象不可变性的保护工具
Requires
- php: ^7.1
Requires (Dev)
- brainmaestro/composer-git-hooks: ^2.8
- friendsofphp/php-cs-fixer: ^2.16
- infection/infection: ^0.13|^0.15|^0.18|^0.19
- overtrue/phplint: ^1.2
- pedrotroller/php-cs-custom-fixer: ^2.19
- phpmd/phpmd: ^2.8
- phpstan/extension-installer: ^1.0.3
- phpstan/phpstan: ^0.12
- phpstan/phpstan-deprecation-rules: ^0.12
- phpstan/phpstan-strict-rules: ^0.12
- phpunit/phpunit: ^7.5|^8.0
- povils/phpmnd: ^2.1
- roave/security-advisories: dev-master
- sebastian/phpcpd: ^4.0
- squizlabs/php_codesniffer: ^3.5
- thecodingmachine/phpstan-strict-rules: ^0.12
README
PHP对象不可变性的保护工具
在PHP中,由于语言的本质,实现真正的对象不可变性是一项不可能的任务。仔细检查和保护属性和方法的可见性是我们目前能做的最接近的事情。
创建一个尽可能不可变的对象需要专业知识、奉献和专注,以确保没有修改机制通过开发者的手进入对象。这就是这个库背后的原因,提供一个帮助确保对象不可变性的方式,以减轻这项繁琐的任务。
安装
Composer
composer require phpgears/immutability
用法
需要composer自动加载文件
require './vendor/autoload.php';
Gears\Immutability\ImmutabilityBehaviour
特质通过在对象构造、__wakeup
方法和unserialize
方法(如果实现了Serializable接口)上调用assertImmutable
方法,强制你避免在类中使用公共属性和可变方法。
提到的行为本身会让你的对象完全无用,你必须提供一个getAllowedInterfaces
抽象方法的实现,返回一个允许在类中使用的接口的列表。虽然你也可以提供类名,这在某些特殊情况下可能有用,但它被强烈反对,并且应该很少使用。
允许定义公开的PHP魔术方法很少,包括__construct
、__destruct
、__get
、__isset
、__sleep
、__wakeup
、__serialize
、__unserialize
、__toString
、__set_state
、__clone
、__debugInfo
。
use Gears\Immutability\ImmutabilityBehaviour; interface MyInterface extends \Serializable { /** * @return string */ public function getParameter(): string; } final class MyClass implements MyInterface { use ImmutabilityBehaviour; protected function __construct() { $this->assertImmutable(); } /** * Static methods are allowed. */ public static function instance(): self { return new self(); } /** * Method allowed because it's defined in the interface. */ public function getParameter(): string { return ''; } /** * Method allowed because it's defined in the \Serializable. */ public function serialize(): string { return ''; } /** * Method allowed because it's defined in the \Serializable. */ public function unserialize($serialized): void { $this->assertImmutable(); // unserialize } /** * {@inheritdoc} */ protected function getAllowedInterfaces(): array { return [MyInterface::class]; } }
一般来说,你的不可变类应该声明为final。如果真的需要继承,至少对于每个可实例化的类,必须将getAllowedInterfaces
方法的实现声明为final。
尽管不是强制性的,但建议将构造函数声明为受保护的,并强制开发者创建静态命名构造函数。
从现在开始,你可以专注于在接口中定义的方法,并确保它们不会修改你的对象,有信心其他开发者不会意外或故意修改你的对象。
示例
如果你想查看不可变对象的工作示例实现,请查看phpgears/identity、phpgears/dto或phpgears/cqrs。
贡献
发现了一个错误或有一个功能请求?请创建一个新的问题。在创建问题之前,请查看现有的问题。
请参阅CONTRIBUTING.md文件。
许可
有关许可条款的副本,请参阅包含在源代码中的LICENSE文件。