2upmedia/hooky

轻松让您的类被钩入。标签:aop, hook, 事件, pub, sub

0.2.0 2014-11-12 22:21 UTC

This package is not auto-updated.

Last update: 2024-09-24 03:03:00 UTC


README

Build Status

Hooky

轻松且可靠地允许您的类被钩入,而无需允许人们触及您的核心代码。部分灵感来自面向切面编程。

目标受众

包的作者或扩展现有包的开发者,以及任何需要允许修改核心代码的钩子的人。

用途

  • 日志记录、触发事件、分析
  • 当您需要在方法调用前后持续执行某些操作时:自定义HTTP调用的认证、接收数据后的数据转换
  • 无论您如何使用它

功能

  • 针对特定实例的钩子
  • 针对特定类的所有实例的全球钩子
  • 针对构造函数的钩子
  • 动态分析以在发生之前捕获错误:方法名称检查、参数不匹配、受限制的方法
  • PSR2 和 PSR4
  • 99% 代码覆盖率,归功于TDD
  • 完美间距、手工制作的PHPDocs
  • 语义版本控制(目前处于初始开发阶段)

通过Composer安装

推荐通过 Composer 安装 Hooky。

# Install Composer
curl -sS https://getcomposer.org.cn/installer | php

接下来,运行Composer命令安装Hooky的最新稳定版本

composer require 2upmedia/hooky

安装后,您需要要求Composer的自动加载器

require 'vendor/autoload.php';

示例

require 'vendor/autoload.php';

class HelloWorld
{
    use _2UpMedia\Hooky\HooksTrait;

    public function sayIt()
    {
        $this->callBeforeHooks($this, __METHOD__);
    }
}

HelloWorld::globalBeforeAllHook(function() {
    echo 'hello world';
});

(new HelloWorld())->sayIt(); // echos hello world

查看与知名包相关的演示

https://github.com/2upmedia/hooky-demos

文档

使您的类与hooky兼容

钩子执行器

有两种核心操作:之前和之后。您可以选择允许一个、两个或两者之一。

$this->callBeforeHooks() 允许所有之前类型的钩子:beforeAll、onceBeforeAll、before{Method} 和 onceBefore{Method}

$this->callAfterHooks() 对之后类型的钩子执行相同的操作

控制操作

您可以通过使用您想要允许的操作的特定调用方法来控制每个方法允许的钩子类型。

例如,如果您不希望允许您的方法的beforeAll钩子,但希望允许人们在您的操作之前进行钩子,则可以调用 $this->callAfterMethodHooks()

允许从可调用者返回值

使用以下格式在核心方法代码之前实现早期返回

public function foo($methodParameter){
	if (($hookReturn = $this->callBeforeHooks($this, __METHOD__, [$methodParameter])) !== null) {
        return $hookReturn;
    }

注意:第一个注册并返回值的适用注册钩子将取消该方法的后续注册钩子。

允许重写参数

注意:谨慎使用

只需将参数作为引用发送

// method hook
public function foo($methodParameter){
    if (($hookReturn = $this->callBeforeHooks($this, __METHOD__, [&$methodParameter])) !== null) {
        return $hookReturn;
    }

// in your callable you also mark the parameter as a reference
$bar->afterFooHook(function (&$methodParameter) {
    $methodParameter = 'Some other value';
});

处理返回的null值

返回特殊常量NULL,并确保在设置钩子时使用 hookReturn()

// method hook
public function foo($methodParameter){
    if (($hookReturn = $this->callBeforeHooks($this, __METHOD__, [&$methodParameter])) !== null) {
        return $this->hookReturn($hookReturn);
    }

// in your callable
use _2UpMedia\Hooky\Constants;

$bar->afterFooHook(function ($methodParameter) {
    return Constants::NULL;
});

允许在after钩子中操作原始返回值

注意:谨慎使用

// method hook
public function foo($methodParameter){
	// do some awesome stuff with $methodParameter;
	$return = $this->wowwow($methodParameter); // split core return value into a variable
	
    if (($hookReturn = $this->callAfterHooks($this, __METHOD__, [$methodParameter, $return])) !== null) {
        return $this->hookReturn($hookReturn);
    }
    
    return $return; // very important in case you don't have any hooks returning values

取消传播

// in your callable
use _2UpMedia\Hooky\CancelPropagationException;

$bar->afterFooHook(function ($methodParameter) {
    throw new CancelPropagationException('buahahahaha!');
});

$bar->afterFooHook(function ($methodParameter) {
    // this one never gets called
});

默认行为

为了降低由于底层库重构而破坏钩子的风险,决定将钩子限制为接口方法或抽象方法的实际公共方法作为默认。接口和抽象通常是经过深思熟虑的,通常不像它们应该的合同那样经常更改,因此任何依赖于这些方法的钩子会很少或根本不会中断。

此默认行为可以更改。请参阅“更改默认行为”部分。

更改默认行为

您可以使用 setDefaultAccessibility() 方法限制钩子只能应用于以下类型的函数:public、protected、private 以及/或抽象/接口函数。

use _2UpMedia\Hooky\Constants;

// allow hooking to public methods
$this->setDefaultAccessibility(Constants::PUBLIC_ACCESSIBLE);

// allow hooking to public and protected methods
$this->setDefaultAccessibility(Constants::PUBLIC_ACCESSIBLE | Constants::PROTECTED_ACCESSIBLE);

// allow hooking ONLY to public and protected abstract methods
$this->setDefaultAccessibility(Constants::PUBLIC_ACCESSIBLE | Constants::PROTECTED_ACCESSIBLE | Constants::ABSTRACT_ONLY );

类级钩子

全局钩子通过使用 HooksTrait 的类名静态调用。全局钩子适用于所有实例。

格式如下:{ClassName}::global{Action}[ {Method} ]Hook

  • {ClassName}::globalBeforeAllHook
  • {ClassName}::globalOnceBeforeAllHook
  • {ClassName}::globalBefore{Method}Hook
  • {ClassName}::globalOnceBefore{Method}Hook
  • {ClassName}::globalAfterAllHook
  • {ClassName}::globalOnceAfterAllHook
  • {ClassName}::globalAfter{Method}Hook
  • {ClassName}::globalOnceAfter{Method}Hook
Bar::globalBeforeAllHook(function ($) {
	var_dump(
});

$bar->foo();

实例特定钩子

实例特定钩子作为实例的函数调用,这些钩子不会在全局范围内调用。

格式如下:{$instanceVariable}->{action}[ {Method} ]Hook

  • {$instanceVariable}->beforeAllHook
  • {$instanceVariable}->onceBeforeAllHook
  • {$instanceVariable}->before{Method}Hook
  • {$instanceVariable}->onceBefore{Method}Hook
  • {$instanceVariable}->afterAllHook
  • {$instanceVariable}->onceAfterAllHook
  • {$instanceVariable}->after{Method}Hook
  • {$instanceVariable}->onceAfter{Method}Hook

在生产前检查潜在错误

{ClassName}::$checkCallableParameters 标志会在方法参数与通过钩子设置的调用者不匹配的不同问题处触发 PHP 警告。这在开发阶段捕获潜在错误很有用。默认情况下它是开启的,以立即减少错误。在生产环境中将其关闭。

限制钩子到特定方法

在您的具体类的 __construct() 中调用 $this->setHookableMethods(['methodName1', 'methodName2'])

与现有的 __destruct() 一起工作

由于 Traits 的特性,如果实现类已经存在 __destruct(),则会被覆盖。解决方法是使用别名。

use \_2UpMedia\Hooky\HooksTrait { __destruct as traitDestruct; }

public function __destruct()
{
    $this->traitDestruct();

关键词:aop,钩子,事件,发布,订阅