jgswift / magery
使用 traits 的 PHP 5.4+ 魔术拦截系统
0.1.1
2014-09-11 10:46 UTC
Requires
- php: >=5.4
Requires (Dev)
- phpunit/phpunit: 3.7.*
- satooshi/php-coveralls: dev-master
This package is not auto-updated.
Last update: 2024-09-28 15:44:29 UTC
README
使用 traits 的 PHP 5.4+ 魔术拦截系统
描述
magery 提供了一个 trait 框架,可以用来钩入对象魔法,即 __get、__set、__unset、__isset 和 __call。
安装
使用 composer 在命令行中安装
php composer.phar require jgswift/magery:0.1.*
使用 composer.json 安装 composer
{ "require": { "jgswift/magery": "0.1.*" } }
依赖
- php 5.4+
使用方法
基本
class Foo { use Magery\Mage; private $bar; public function __construct() { $this->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->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!'
读取
可以通过事件拦截任何对象的属性或方法。
注意:多个已注册的事件将按添加的顺序(FIFO)触发,直到事件返回一个响应值。
class Foo { use magery\Mage; public function __construct() { $this->read('bar', function(){ return 'baz'; }); // Shortcut method $this->read('buzz', function() { return 'bar'; }); } } $foo = new Foo(); echo $foo->bar; // 'baz' echo $foo->buzz; // 'bar'
存在性
class User { private $firstName; private $lastName; function __construct($firstName, $lastName) { /* ... */ } } $user = new User('John', 'Doe'); $user->exists('lastName', function()use(&$c) { return isset($this->lastName); // do something extra for existence check }); var_dump(isset($user->lastName)); // true
移除
$user = new User('Joe','Smith'); $user->remove('name', function()use(&$c) { unset($this->name); // do something extra for remove }); unset($user->name); var_dump(isset($user->name)); // false
结果缓存
如果事件返回响应,则可以将其缓存以减少未来读取的执行时间。
public $bar = 'Bill'; public function __construct() { $this->read('bar', function(){ sleep(1); return microtime(); }, true); // pass in "true" here (defaults to false) } $foo = new Foo(); var_dump($foo->bar === $foo->bar); // true
辅助方法作用域
除了 magery 函数默认受保护外,所有事件都是全局注册的。
<?php class Foo { use Magery\Mage {magery as public;} // allow public event registration public $bar; } $foo = new Foo(); $foo->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!'
调用
与读取类似,调用魔法也可能缓存结果以减少未来调用的执行时间。
<?php class Foo { use Magery\Mage; } $foo = new Foo(); $foo->call('bar', function() { sleep(1); return microtime(); },true); var_dump($foo->bar() === $foo->bar()); // true
可数组的对象
对于数组而不是对象,通过结合使用 ArrayAccess 和 MageAccess trait 将提供与数组语法相同的魔法机会
<?php class Foo implements ArrayAccess { use Magery\MageAccess; } $foo = new Foo(); $foo->read('bar', function() { return 'baz'; }); var_dump($foo['bar']); // baz
自定义魔法处理器
您可以通过选择性地使用 traits 来创建自定义处理器。
此示例类仅包含写入魔法,所有其他操作都原生执行,不中断。自定义对象必须使用 Magery\Object
,并且您可以选择任何组合的 Traits/Read
、Traits/Write
、Traits/Remove
、Traits/Exists
trait 来应用特定的魔法功能。
<?php class Foo { use Magery\Object, Magery\Traits\Write; } $foo = new Foo(); $foo->write('bar', function($v){ $this->baz = $v; }); $foo->bar = 'somethingImportant'; var_dump($foo->baz); // somethingImportant