定制 divineniiquaye/php-invoker 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

divineniiquaye/php-invoker

Composer 安装命令:

composer require divineniiquaye/php-invoker

包简介

A library that provides the abilities to invoking callables with named parameters in a generic and extensible way.

README 文档

README

Latest Version Software License Workflow Status Code Maintainability Coverage Status Quality Score Sponsor development of this project

divineniiquaye/php-invoker is a php library that allows invoking callables with named parameters in a generic and extensible way for PHP 7.1+, based on reference implementation PHP-DI Invoker created by Matthieu Napoli. This library provides clear extension points to let frameworks/projects implement any kind of dependency injection support they want, but not limited to dependency injection. Again, any PSR-11 compliant container can be provided.

📦 Installation & Basic Usage

This project requires PHP 7.1 or higher. The recommended way to install, is via Composer. Simply run:

$ composer require divineniiquaye/php-invoker

Let's say you working on a project and want to invoke some named parameters in callables with whatever the order of parameters, but should be matched by their names or instance. Then we'll need an over-engineered call_user_func().

In short, this library is meant to be a base building block for calling a function with named parameters and/or dependency injection.

Using DivineNii\Invoker\Invoker class method 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');

Using DivineNii\Invoker\ArgumentResolver class in DivineNii\Invoker\Invoker class:

Extending the behavior of the DivineNii\Invoker\Invoker is easy and is done by adding a callable to ArgumentResolver class:

use ReflectionParameter;
use DivineNii\Invoker\Interfaces\ArgumentValueResolverInterface;

class MyParameterValueResolver implements ArgumentValueResolverInterface
{
    /**
     * {@inheritdoc}
     */
    public function resolve(ReflectionParameter $parameter, array $providedParameters)
    {
        //....
    }
}
  • $providedParameters contains the parameters provided by the user when calling $invoker->call($callable, $parameters)

An DivineNii\Invoker\Invoker can chain multiple parameter resolvers to mix behaviors, e.g. you can mix "named parameters" support with "dependency injection" support.

Here is an implementation example for dumb dependency injection that creates a new instance of the classes type-hinted:

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) {
                // ...
            }
        }
    }
}

To use it:

$invoker = new DivineNii\Invoker\Invoker([new MyParameterValueResolver()]);

$invoker->call(function (ArticleManager $articleManager) {
    $articleManager->publishArticle('Hello world', 'This is the article content.');
});

A new instance of ArticleManager will be created by our parameter resolver. The fun starts to happen when we want to add support for many things:

  • named parameters
  • dependency injection for type-hinted parameters
  • ...

It allows to support even the weirdest use cases like:

$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);

Rather than have you re-implement support for dependency injection with different containers every time, this package ships with 2 optional resolvers:

  • This resolver will inject container entries by searching for the class name using the type-hint:

    $invoker->call(function (Psr\Logger\LoggerInterface $logger) {
        // ...
    });

    In this example it will ->get('Psr\Logger\LoggerInterface') from the container and inject it, but if instance of interface exist in $providedParameters, it also get injected.

  • This resolver will inject container entries by searching for the name of the parameter:

    $invoker->call(function ($twig) {
        // ...
    });

    In this example it will ->get('twig') from the container and inject it or from $providedParameters.

The DivineNii\Invoker\Invoker can be wired to your DI container to resolve the callables, but can resolve all callables including invokable class or object.

For example with an invokable class:

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');

The same works for a class method:

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');

📓 Documentation

For in-depth documentation before using this library. Full documentation on advanced usage, configuration, and customization can be found at docs.biurad.com.

⏫ Upgrading

Information on how to upgrade to newer versions of this library can be found in the UPGRADE.

🏷️ Changelog

SemVer is followed closely. Minor and patch releases should not introduce breaking changes to the codebase; See CHANGELOG for more information on what has changed recently.

Any classes or methods marked @internal are not intended for use outside of this library and are subject to breaking changes at any time, so please avoid using them.

🛠️ Maintenance & Support

When a new major version is released (1.0, 2.0, etc), the previous one (0.19.x) will receive bug fixes for at least 3 months and security updates for 6 months after that new release comes out.

(This policy may change in the future and exceptions may be made on a case-by-case basis.)

Professional support, including notification of new releases and security updates, is available at Biurad Commits.

👷‍♀️ Contributing

To report a security vulnerability, please use the Biurad Security. We will coordinate the fix and eventually commit the solution in this project.

Contributions to this library are welcome, especially ones that:

  • Improve usability or flexibility without compromising our ability to adhere to PSR-12 coding stardand.
  • Optimize performance
  • Fix issues with adhering to PSR-11 support and backward compatability.

Please see CONTRIBUTING for additional details.

🧪 Testing

$ composer test

This will tests divineniiquaye/php-invoker will run against PHP 7.2 version or higher.

👥 Credits & Acknowledgements

🙌 Sponsors

Are you interested in sponsoring development of this project? Reach out and support us on Patreon or see https://biurad.com/sponsor for a list of ways to contribute.

📄 License

divineniiquaye/php-invoker is licensed under the BSD-3 license. See the LICENSE file for more details.

🏛️ Governance

This project is primarily maintained by Divine Niiquaye Ibok. Members of the Biurad Lap Leadership Team may occasionally assist with some of these duties.

🗺️ Who Uses It?

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us an email or message mentioning this library. We publish all received request's at https://patreons.biurad.com.

Check out the other cool things people are doing with divineniiquaye/php-invoker: https://packagist.org/packages/divineniiquaye/php-invoker/dependents

divineniiquaye/php-invoker 适用场景与选型建议

divineniiquaye/php-invoker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 10.19k 次下载、GitHub Stars 达 3, 最近一次更新时间为 2020 年 08 月 10 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「resolver」 「invoker」 「PHP7」 「biurad」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 divineniiquaye/php-invoker 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 divineniiquaye/php-invoker 我们能提供哪些服务?
定制开发 / 二次开发

基于 divineniiquaye/php-invoker 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 10.19k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 17
  • 依赖项目数: 2
  • 推荐数: 1

GitHub 信息

  • Stars: 3
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2020-08-10