jclaveau/php-deferred-callchain
Composer 安装命令:
composer require jclaveau/php-deferred-callchain
包简介
Register a chain of calls that will be applied on an instance later
README 文档
README
This class simply provides a way to define fluent chain of methods, functions, array access calls before having the target (object or native value) you wan't to apply it to. Once the expected targets are available, simply call the chain on them as if it was a function.
Quality
Overview
// having class MyClass { protected $name = 'unnamed'; public function setName($name) { $this->name = $name; return $this; } public function nameEntries() { return [ 'my_entry_1' => $this->name . " 1", 'my_entry_2' => $this->name . " 2", ]; } } // We can define some chained calls (none is executed) $doDummyCallsLater = DeferredCallChain::new_( MyClass::class ) // Targets must be MyClass instances ->nameEntries()['my_entry_2'] // access array entry ->strtoupper() // apply strtoupper() to it ; // do whatever we want // ... // Get your targets $myInstance1 = (new MyClass)->setName('foo'); $myInstance2 = (new MyClass)->setName('bar'); // Execute the callchain echo $doDummyCallsLater( $myInstance1 ); // => FOO 2 echo $doDummyCallsLater( $myInstance2 ); // => BAR 2
Installation
php-deferred-callchain is installable via Composer
composer require jclaveau/php-deferred-callchain
Testing
Tests are located here and runnable by calling
./phpunit
Usage
- Functionnal and chained construction
- Fluent call chain
- Working with arrays
- Working with native types and functions
- Specifying on which class, interface, type or instance, the chain is callable
- Calls provoking exceptions
- Static calls
- API Reference
Functionnal and chained construction
DeferredCallChain can be instanciated classically
$nameRobert = (new DeferredCallChain(Human::class))->...
Statically
$nameRobert = DeferredCallChain::new_(Human::class)->...
Or functionnaly
$nameRobert = later(Human::class)->...
Fluent call chain
$nameRobert = DeferredCallChain::new_() ->setName('Muda') ->setFirstName('Robert') ; $mySubjectIMissedBefore = new Human; $robert = $nameRobert( $mySubjectIMissedBefore ); echo $robert->getFullName(); // => "Robert Muda" echo (string) $nameRobert; // => "(new JClaveau\Async\DeferredCallChain)->setName('Muda')->setFirstName('Robert')"
Working with arrays
$getSubColumnValue = DeferredCallChain::new_() ['column_1'] ['sub_column_3'] ; $sub_column_3_value = $getSubColumnValue( [ 'column_1' => [ 'sub_column_1' => 'lalala', 'sub_column_2' => 'lololo', 'sub_column_3' => 'lilili', ], 'column_2' => [ 'sub_column_1' => 'lululu', 'sub_column_2' => 'lelele', 'sub_column_3' => 'lylyly', ], ] ); echo $sub_column_3_value; // => "lilili" echo (string) $getSubColumnValue; // => "(new JClaveau\Async\DeferredCallChain)['column_1']['sub_column_3']"
Working with native types and functions
The features above make calls to objects methods easy and async but when their result is not an object, the fluent syntax has to stop, and the async behavior also.
Based on Daniel S Deboer work https://github.com/danielsdeboer/pipe, support of chained function calls has been added.
class MyClass { public function getString() { return 'string'; } } $upperifyMyClassString = DeferredCallChain::new_( MyClass::class ) ->getString() ->strtoupper(); echo $upperifyMyClassString( new MyClass ); // prints "STRING"
Some functions do not use the subject of the fluent syntax as first argument. In this case, giving '$$' as the parameter you want to be replaced by the subject.
class MyClass { public function getSentence() { return 'such a funny lib to implement'; } } $explodeMyClassSentence = DeferredCallChain::new_( MyClass::class ) ->getSentence() ->explode(' ', '$$'); $explodeMyClassSentence( new MyClass ); // returns ['such', 'a', 'funny', 'lib', 'to', 'implement']
Specifying on which class, interface, type or instance, the chain is callable
You can force the target of your call chain to:
- be an instance of a specific class
$nameRobert = DeferredCallChain::new_(Alien::class) ->setName('Muda') ->setFirstName('Robert') ; $mySubjectIMissedBefore = new Human; $robert = $nameRobert( $mySubjectIMissedBefore ); // throws BadTargetClassException
- implement a specific interface
$getCount = DeferredCallChain::new_("\Traversable") ->count() ; $myCountableIMissedBefore = new CountableClass; // class implementing Countable // throws BadTargetInterfaceException
- be of a specific native type
$nameRobert = DeferredCallChain::new_("array") ->setName('Muda') ->setFirstName('Robert') ; $mySubjectIMissedBefore = new Human; $robert = $nameRobert( $mySubjectIMissedBefore ); // throws BadTargetTypeException
- be a specific instance given at construction
$myTarget = new Human; $nameRobert = DeferredCallChain::new_($myTarget) ->setName('Muda') ->setFirstName('Robert') ; $robert = $nameRobert( new Human ); // throws TargetAlreadyDefinedException
Calls provoking exceptions
As a call can be made far before it's effectivelly applied, exceptions need more debug information for a smooth workflow. To achieve that, a line is added to every exception message thrown during a DeferredCallChain execution, pointing to the buggy call and where it is coded.
For example, an exception having as message An exception has been thrown by some user code
will print
An exception has been thrown by some user code
When applying (new JClaveau\Async\DeferredCallChain( <instance id> ))->previousSuccessfullCall()->buggyCall('Robert') defined at <file>:<line>
Static calls
Static calls can be useful, especially for singletons. For some technical reasons explained here, the only way to support it is to call them as normal methods (e.g. with -> ) and look for it as a static method once we know it doesn't exist as a regular one.
later(MyModel::class)->getInstance()->myNormalGetter(); // or later($myModel)->getInstance()->myNormalGetter(); // like $myModel::getInstance()
jclaveau/php-deferred-callchain 适用场景与选型建议
jclaveau/php-deferred-callchain 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 6.97k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2018 年 11 月 06 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「fluent」 「lazy」 「asynchronous」 「Chain」 「promise」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 jclaveau/php-deferred-callchain 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 jclaveau/php-deferred-callchain 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 jclaveau/php-deferred-callchain 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Lazy loading for middleware and request handlers
LazyPDO is a set of wrappers over PHP's standard PDO and PDOStatement classes. It enables lazy loading, serialization and decoration.
Presentation and Formatting helper with nice fluent interface.
Traits gathering fluent syntax common methods
A modern, fluent HTTP client. Forked from Mashape, reimagined by Nidux, and open-sourced for the PHP community.
A fluent PHP CURL wrapper
统计信息
- 总下载量: 6.97k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 15
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2018-11-06