phata / hook
基于PHP的接口特性和PSR-11容器的最小化钩子库。
v1.1.0
2018-09-19 09:14 UTC
Requires
- php: >=7.1
- psr/container: ^1.0
Requires (Dev)
Suggests
- php-di/php-di: PSR-11 Container implementation that with dependency injection and autowiring
This package is auto-updated.
Last update: 2024-09-27 10:17:54 UTC
README
基于PHP的接口特性和PSR-11容器的最小化钩子库。
为什么
许多CMS(如Drupal、Wordpress)基于钩子系统进行模块化。它们通常是这样工作的
- CMS在其文档中某处声明钩子。
- 并提供一种方式让模块声明它们实现了任何钩子。
- 模块按照文档实现钩子。
- 在CMS中某个地方,当钩子“调用”时,从(3)中收集所有实现并针对某些数据进行运行。收集返回值。
它们通常也允许模块声明自己的钩子。但它们需要自己实现(4)。CMS会提供辅助API来调用钩子。
此库提供了一种现代方式来实现。
安装
推荐方法是使用composer
composer require "phata/hook"
然后您应该能够使用composer的自动加载。
示例用法
基本的调用映射和归约
```php // composer的自动加载器路径 require_once '../vendor/autoload.php'; $container = new DI\Container; // 或其他PHP-11兼容的容器 $registry = new Phata\Hook\Registry; $invoker = new Phata\Hook\Invoker($registry, $container); // 将现有接口声明为钩子。 $registry->declareHooks([ App\MyInterface::class, SomeAwesomeLibrary\Interface::class, ]); // 将类添加到注册表中,它会自动针对声明的钩子进行索引。 $registry->add([ App\MyModule1::class, App\MyModule2::class, FooBar\External\Module::class, ]); // 使用$invoker来调用钩子 // 使用1:映射结果 $array = $invoker->map( App\MyInterface::class, function (App\MyInterface $module) { return $module->doSomething(); } ); // 使用2:归约 $result = $invoker->reduce( App\MyInterface::class, function ($carry, App\MyInterface $module) { return $module->process($carry); }, $someInitialValue ); ```高级示例
使用排序调用者有序模块
```php nameapace App; use Phata\Hook\SortableInterface; class MyModule1 implements SortableInterface, MyInterface { public function myProcess($input) { // 对$input的一些处理 // ... return $output; } public function getWeight():int { // 获取模块权重的一些逻辑 // 可能来自数据库操作 // ... return $weight; } } ``` ```php // composer的自动加载器路径 require_once '../vendor/autoload.php'; $container = new DI\Container; // 或其他PHP-11兼容的容器 $registry = new Phata\Hook\Registry; $invoker = new Phata\Hook\SortingInvoker($registry, $container); // 将现有接口声明为钩子。 $registry->declareHooks([ Psr\Http\Server\MiddlewareInterface::class, ]); // 将类添加到注册表中,它会自动针对声明的钩子进行索引。 $registry->add([ App\MyModule1::class, App\MyModule2::class, FooBar\External\Module::class, ]); // 处理请求 // // 注意:排序调用者将在调用之前根据权重排序模块。 $results = $invoker->map( App\MyInterface::class, function (App\MyInterface $module) use ($input) { return $module->process($input); } ); // 使用$results //... ```使用PSR-7请求与PSR-15中间件进行消费
```php // composer的自动加载器路径 require_once '../vendor/autoload.php'; $container = new DI\Container; // 或者其他PHP-11兼容的容器 $registry = new Phata\Hook\Registry; $invoker = new Phata\Hook\Invoker($registry, $container); // 声明现有接口为钩子。 $registry->declareHooks([ Psr\Http\Server\MiddlewareInterface::class, ]); // 将类添加到注册表中,它会自动针对声明的钩子进行索引。 $registry->add([ App\MyModule1::class, App\MyModule2::class, FooBar\External\Module::class, ]); // 处理请求 $request = $invoker->reduce( Psr\Http\Server\MiddlewareInterface::class, function ($request, Psr\Http\Server\MiddlewareInterface::class $middleware) { return $middleware->process($request); }, GuzzleHttp\Psr7\ServerRequest::fromGlobals() ); // 处理程序处理请求 //... ```使用`$carry`聚合简化PSR-7请求
```php // composer的自动加载器路径 require_once '../vendor/autoload.php'; $container = new DI\Container; // 或者其他PHP-11兼容的容器 $registry = new Phata\Hook\Registry; $invoker = new Phata\Hook\Invoker($registry, $container); // 声明现有接口为钩子。 $registry->declareHooks([ App\Middleware\Interface::class, ]); // 将类添加到注册表中,它会自动针对声明的钩子进行索引。 $registry->add([ App\MyModule1::class, App\MyModule2::class, FooBar\External\Module::class, ]); // 处理请求 $request = GuzzleHttp\Psr7\ServerRequest::fromGlobals(); $result = $invoker->reduce( App\Middleware\Interface::class, function ($carry, App\Middleware\Interface::class $middleware) use ($request) { $middleware->process($carry, $request); return $carry; }, null ); ```文档
Phata\Hook的类和类型文档可以在这里找到。
许可
Phata\Hook遵循MIT许可协议分发。您应该已经收到了Phata/Hook附带的GNU Lesser General Public License副本。如果没有,请参阅https://open-source.org.cn/licenses/MIT。