PHP 变量事件。

0.1.0 2014-03-04 17:17 UTC

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'];
  • 添加一个方法来从代理中删除变量(以提高性能)