leedavis81 / vent
PHP 变量事件。
Requires
- php: >=5.4
Requires (Dev)
- phpunit/phpunit: 3.7.*
- satooshi/php-coveralls: ~0.6
This package is not auto-updated.
Last update: 2024-09-14 15:17:12 UTC
README
PHP 变量事件系统
| 质量 / 指标 | 发布版本 | 下载次数 | 许可证 | | ----- | -------- | ------- | ------------- | -------- |
|
|
|
安装
通过 composer 安装
php composer.phar require leedavis81/vent:dev-master
用法
你是否需要钩子事件,每当PHP变量被读取时?也许你想要确保即使在类的私有作用域内也能保持完全不可变性。可以通过钩子任何变量的读取或写入来轻松创建PHP变量事件。
<?php class Foo { use Vent\VentTrait; private $bar; public function __construct() { $this->registerEvent('read', 'bar', function(){ throw new \Exception('Don\'t touch my bar!'); }); } public function touchBar() { $this->bar; } } $foo = new Foo(); $foo->touchBar(); // Fatal error: Uncaught exception 'Exception' with message 'Don't touch my bar!'
或者,你可以注册一个写入事件来保护变量不被覆盖(即使在你的类的作用域内)
$this->registerEvent('write', 'bar', function(){ throw new \Exception('Don\'t write to my bar!'); }); public function writeToBar() { $this->bar = 'somethingElse'; } $foo = new Foo(); $foo->writeToBar(); // Fatal error: Uncaught exception 'Exception' with message 'Don't write to my bar!'
你可以通过从注册的事件返回一些内容来伪装任何值。注意,如果有多个事件被注册,一旦其中一个返回响应,执行将停止。它们将按照注册的顺序触发(先进先出)。
public $bar = 'Bill'; public function __construct() { $this->registerEvent('read', 'bar', function(){ return 'Ben'; }); } $foo = new Foo(); echo $foo->bar; // "Ben"
要向你的方法传递参数,只需在注册事件时提供它们。
请注意,有两个保留字符串,如果作为参数传入,将被替换
_OVL_NAME_
替换为你访问的变量名(设置或获取)_OVL_VALUE_
替换为更新变量的值(仅设置)_CUR_VALUE_
变量的当前值
public $bar = 'chips'; public function __construct() { $this->registerEvent('write', 'bar', function($var1, $name, $value, $cur_value){ echo 'Why ' . $var1 . ' you\'re trying to overwrite "' . $name . '", which contained "' . $cur_value . '" to contain "' . $value . '"'; }, ['bill', '_OVL_NAME_', '_OVL_VALUE_', '_CUR_VALUE_']); } $foo = new Foo(); $foo->bar = 'cheese'; // Why bill you're trying to overwrite "bar", which contained "chips" to contain "cheese"
如果你在事件中返回响应,这可以保留以防止进一步的读取执行。如果你从操作中没有返回任何内容(或返回null),则不保留任何内容,并且额外的读取将导致重新执行注册的操作。
public $bar = 'Bill'; public function __construct() { $this->registerEvent('read','bar', function(){ sleep(1); return microtime(); }, null, true); // pass in "true" here (defaults to false) } $foo = new Foo(); var_dump($foo->bar === $foo->bar); // true
在使用 VentTrait
时,所有事件必须在你的类的上下文中注册。然而,如果你想从公共或受保护的作用域注册它们,只需在导入特质时更改 registerEvent
方法的范围即可。
<?php class Foo { use Vent\VentTrait {registerEvent as public;} // allow public event registration public $bar; } $foo = new Foo(); $foo->registerEvent('read', 'bar', function(){ throw new \Exception('Don\'t touch my bar!'); }); $foo->bar; // Fatal error: Uncaught exception 'Exception' with message 'Don't touch my bar!'
支持的事件
但你偷走了我的魔法
确实,这个小特质为你的类应用了一个 __get
和 __set
方法。如果你的类已经有了一些魔法,并且这些方法已经被应用,那么它们将覆盖特质实现。这可能不是你想要的。为了解决这个问题,你可以简单地使用不同的方法名导入它们,并在你自己的魔法方法中调用它们。例如
class Foo() { use Vent\VentTrait {__get as get;} public function __get($name) { // You're own magic stuff will go here. return $this->get($name); // Fire off the vent magic (if you need it) } }
待办事项
- 允许事件触发数组偏移量读取 $foo->bar['offset'];
- 添加一个方法来从代理中删除变量(以提高性能)