intahwebz/weaver

此包已被废弃,不再维护。未建议替代包。

组合编程的实验。

0.4.5 2014-11-06 17:55 UTC

This package is auto-updated.

Last update: 2020-06-19 11:47:35 UTC


README

组合编程的实验。受https://github.com/Ocramius/ProxyManagerhttps://github.com/ejsmont-artur/phpProxyBuilder的启发

Build Status

为什么?

上面列出的两个项目都是好主意,但存在严重的局限性。phpProxyBuilder无法生成正确的类型提示信息,这完全阻止了我使用它。

ProxyManager很棒,但与其他代码交互时有问题,似乎使得调试代码变得极其困难。我也看不到如何实现缓存代理。

本项目试图生成各种装饰类版本,目标是

  • 在如何使用它们方面具有极大的灵活性。

  • 保留调试代码的能力。

  • 心理和代码重量都低。

  • 保持类型提示完整,以便Auryn DI可以正确工作。

示例

我们有一个类,我们想能够计时'executeQuery'的调用


class TestClass {

    function __construct($statement, $createLine){
        $this->statement = $statement;
        $this->createLine = $createLine;
    }

    function executeQuery($queryString, $foo2) {
        echo "executing query!";
        
        return 5;
    }
}

用包含计时器的'class'进行编织

<?php


namespace Weaver\Weave;

use Intahwebz\Timer;


class TimerProxy {

    private $timer;

    function __construct(Timer $timer) {
        $this->timer = $timer;
    }

    function reportTimings() {
        $this->timer->dumpTime();
    }
}

并用一点胶水将两者绑定

$timerWeaving = array(
    'executeQuery' => array(
        '$this->timer->startTimer($queryString);', 
        '$this->timer->stopTimer();'
    ),
);

产生装饰类

<?php
namespace Example;

use Intahwebz\Timer;

class TimerProxyXTestClass extends \Example\TestClass
{

    private $timer = null;

    public function executeQuery($queryString, $foo2)
    {
        $this->timer->startTimer($queryString);
        $result = parent::executeQuery($queryString, $foo2);
        $this->timer->stopTimer();

        return $result;
    }

    public function reportTimings()
    {
        $this->timer->dumpTime();
    }

    public function __construct($statement, $createLine, \Intahwebz\Timer $timer)
    {
        parent::__construct($statement, $createLine);
                $this->timer = $timer;
    }

}

因为我使用真正的DI,现在我可以将配置更改以包含

$injector->alias(TestClass::class, TimerProxyXTestClass::class);

并且附加计时器的代理版本将在原类被使用的任何地方使用。

待办事项

  • 弄清楚如何处理工厂,因为不得不为每种组合创建一个新的工厂真的很糟糕。例如,CachedTimedStatementWrapperFactory用于创建缓存、计时、语句包装器工厂。

  • 写一篇关于此与猴子补丁http://en.wikipedia.org/wiki/Monkey_patch的区别的文章。简而言之,猴子补丁仅运行时,无法调试,类型安全性不高。

术语

  • 源类 - 需要修改其行为的原始类。

  • 装饰类 - 将用于装饰源类的类。

  • 装饰类 - 编织的结果。

备注

我应该从Ocramius/ProxyManager实施的一组示例

延迟加载值持有者(虚拟代理)访问拦截器值持有者空对象幽灵对象 - 用于延迟加载延迟引用 - wat远程对象

保护代理类APIProtectionProxy extends API { protected $count = 0; public function __construct(API $api, $limit) { $this->api = $api; $this->limit = $limit; }

public function doStuff() {
    $this->count();
    return $this->api->doStuff();
}

private function count() {
    if (++$this->count > $this->limit) {
        throw new RemoteApiLimit('STAHP!');
    }
}

}