divineniiquaye / php-invoker
一个库,以通用和可扩展的方式提供调用具有命名参数的可调用项的能力。
Requires
- php: ^7.1 || ^8.0
- psr/container: ^1.1|^2.0
- symfony/polyfill-php80: ^1.20
Requires (Dev)
- composer/package-versions-deprecated: ^1.11
- phpstan/phpstan: ^0.12
- phpstan/phpstan-strict-rules: ^0.12
- phpunit/phpunit: ^8.5 || ^9.5
- squizlabs/php_codesniffer: ^3.5
- vimeo/psalm: ^3.11 || 4.4.*
README
divineniiquaye/php-invoker 是一个 PHP 库,允许以通用和可扩展的方式调用具有命名参数的可调用项,基于由 PHP-DI Invoker 创建的引用实现,由 Matthieu Napoli 构建。此库提供了清晰的扩展点,以便框架/项目实现他们想要的任何类型的依赖注入支持,但不仅限于依赖注入。再次强调,任何符合 PSR-11 的容器都可以提供。
📦 安装与基本用法
此项目需要 PHP 7.1 或更高版本。推荐的安装方式是通过 Composer。只需运行
$ composer require divineniiquaye/php-invoker
假设你在做项目,并想在可调用项中调用一些命名参数,但这些参数的顺序可以是任意的,但应按名称或实例匹配。那么我们就需要一个过度设计的 call_user_func()
。
简而言之,这个库旨在成为一个调用带命名参数的函数的基础构建块,并支持依赖注入。
使用 DivineNii\Invoker\Invoker
类的 call
方法
$invoker = new DivineNii\Invoker\Invoker; $invoker->call(function () { echo 'Hello world!'; }); // Simple parameter array $invoker->call(function ($name) { echo 'Hello ' . $name; }, ['John']); // Named parameters $invoker->call(function ($name) { echo 'Hello ' . $name; }, [ 'name' => 'John' ]); // Typehint parameters $invoker->call(function (string $name) { echo 'Hello ' . $name; }, [ 'name' => 'John' ]); // Use the default value $invoker->call(function ($name = 'world') { echo 'Hello ' . $name; }); // Invoke any PHP callable $invoker->call(['MyClass', 'myStaticMethod']); // Using Class::method syntax $invoker->call('MyClass::myStaticMethod'); // Using ":" pattern syntax $invoker->call('MyClass:myMethod'); // Using "@" pattern syntax $invoker->call('MyClass@myMethod');
使用 DivineNii\Invoker\ArgumentResolver
类在 DivineNii\Invoker\Invoker
类中
扩展 DivineNii\Invoker\Invoker
的行为很容易,只需将可调用项添加到 ArgumentResolver
类中即可
use ReflectionParameter; use DivineNii\Invoker\Interfaces\ArgumentValueResolverInterface; class MyParameterValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function resolve(ReflectionParameter $parameter, array $providedParameters) { //.... } }
$providedParameters
包含用户在调用$invoker->call($callable, $parameters)
时提供的参数
DivineNii\Invoker\Invoker
可以连接多个参数解析器以混合行为,例如,您可以混合“命名参数”支持与“依赖注入”支持。
以下是一个实现示例,用于创建由类型提示指定的类的新实例的简单依赖注入
use {ReflectionClass, ReflectionException}; use DivineNii\Invoker\Interfaces\ArgumentValueResolverInterface; class MyParameterValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function resolve(ReflectionParameter $parameter, array $providedParameters) { $parameterClass = $parameter->getClass(); if ($parameterClass instanceof ReflectionClass) { try { return $class->newInstance(); } catch (ReflectionExcetion $e) { // ... } } } }
要使用它
$invoker = new DivineNii\Invoker\Invoker([new MyParameterValueResolver()]); $invoker->call(function (ArticleManager $articleManager) { $articleManager->publishArticle('Hello world', 'This is the article content.'); });
我们的参数解析器将创建一个 ArticleManager
的新实例。当我们要添加对许多事物的支持时,乐趣就开始了
- 命名参数
- 类型提示参数的依赖注入
- ...
它甚至支持最奇怪的使用案例,例如
$parameters = []; // First parameter will receive "Welcome" $parameters[] = 'Welcome'; // Parameter named "content" will receive "Hello world!" $parameters['content'] = 'Hello world!'; // $published is not defined so it will use its default value $invoker->call(function ($title, $content, $published = true) { // ... }, $parameters);
而不是每次都重新实现支持不同容器的依赖注入,此包附带两个可选解析器
-
此解析器将通过使用类型提示搜索类名来注入容器条目
$invoker->call(function (Psr\Logger\LoggerInterface $logger) { // ... });
在这个例子中,它将从容器中注入
->get('Psr\Logger\LoggerInterface')
,但如果接口的实例存在于$providedParameters
中,它也将被注入。 -
此解析器将通过搜索参数的名称来注入容器条目
$invoker->call(function ($twig) { // ... });
在这个例子中,它将从容器中注入
->get('twig')
或从$providedParameters
中注入。
DivineNii\Invoker\Invoker
可以连接到您的 DI 容器以解析可调用项,但可以解析所有可调用项,包括可调用类或对象。
例如,对于可调用的类
class MyHandler { public function __invoke() { // ... } } // By default this work $invoker->call('MyHandler'); // If we set up the container to use $invoker = new Invoker\Invoker([], $container); // Now 'MyHandler' parameters is resolved using the container if any! $invoker->call('MyHandler');
对于类方法,效果相同
class WelcomeController { public function home() { // ... } } // By default this doesn't work: home() is not a static method $invoker->call(['WelcomeController', 'home']); // If we set up the container to use $invoker = new Invoker\Invoker([], $container); // Now 'WelcomeController' is resolved using the container! $invoker->call(['WelcomeController', 'home']); // Alternatively we can use the Class::method syntax $invoker->call('WelcomeController::home');
📓 文档
在使用此库之前,请查看深度文档。有关高级使用、配置和定制的完整文档,请访问docs.biurad.com。
⏫ 升级
有关如何升级到此库的新版本的说明,请参阅UPGRADE。
🏷️ 更新日志
严格遵守SemVer。次要版本和补丁版本不应引入对代码库的破坏性更改;有关最近更改的更多信息,请参阅CHANGELOG。
任何标记为@internal
的类或方法都不是为了在库外使用,并且可能会随时进行破坏性更改,因此请避免使用它们。
🛠️ 维护与支持
当发布一个新的主要版本(如1.0
、2.0
等)时,上一个版本(如0.19.x
)将在新版本发布后至少3个月内收到错误修复,并在之后的6个月内收到安全更新。
(此政策可能在未来发生变化,并且可能会根据具体情况做出例外。)
专业支持,包括通知新版本和安全更新,可在Biurad Commits处获得。
👷♀️ 贡献
要报告安全漏洞,请使用Biurad Security。我们将协调修复,并最终在此项目中提交解决方案。
欢迎对此库的贡献,特别是以下贡献:
有关详细信息,请参阅CONTRIBUTING。
🧪 测试
$ composer test
这将测试divineniiquaye/php-invoker是否可在PHP 7.2版本或更高版本上运行。
👥 信用与鸣谢
🙌 赞助商
您有兴趣赞助此项目的发展吗?请与我们联系,在Patreon上支持我们,或查看https://biurad.com/sponsor上的赞助方式。
📄 许可证
divineniiquaye/php-invoker遵循BSD-3许可证。有关更多详细信息,请参阅LICENSE
文件。
🏛️ 治理
此项目主要由Divine Niiquaye Ibok维护。Biurad Lap领导团队的一些成员有时会协助这些职责。
🗺️ 使用者
您可以自由使用此包,但如果它进入了您的生产环境,我们非常欢迎您发送一封电子邮件或消息,提及此库。我们将在https://patreons.biurad.com上发布所有收到的请求。
查看人们用 divineniiquaye/php-invoker
做的其他酷炫事情:https://packagist.org.cn/packages/divineniiquaye/php-invoker/dependents