项目作者: leocavalcante

项目描述 :
🕊️ Event dispatcher awareness made simple.
高级语言: PHP
项目地址: git://github.com/leocavalcante/dispatch.git
创建时间: 2021-02-12T23:54:37Z
项目社区:https://github.com/leocavalcante/dispatch

开源协议:MIT License

下载


dispatch() CI Typed codecov

🕊️ Event dispatcher awareness made simple.

Install

  1. composer require leocavalcante/dispatch:dev-main

Usage

Define a dispatcher

It can be anyone that implements the PSR-14 Event Dispatcher Interface.

  1. use function Dispatch\use_dispatcher;
  2. use_dispatcher(Psr\EventDispatcher\EventDispatcherInterface);

Then just call dispatch()

  1. use function Dispatch\dispatch;
  2. dispatch(new MyEvent());

The idea is exactly to make it able to dispatch events from anywhere in your code avoiding EventDispatcherInterface injection boilerplate.

Example

  1. use League\Event\EventDispatcher;
  2. use function Dispatch\{dispatch, use_dispatcher};
  3. class UpperCased {
  4. public function __construct(
  5. public string $result,
  6. ) {}
  7. }
  8. function to_upper(string $str): string {
  9. // Do something
  10. $upper_case_str = strtoupper($str);
  11. // And dispatch an Event without EventDispatcherInterface injection boilerplate
  12. dispatch(new UpperCased($upper_case_str));
  13. return $upper_case_str;
  14. }
  15. class UpperCauser {
  16. public function toUpper(string $str): string {
  17. // Do something
  18. $upper_case_str = strtoupper($str);
  19. // And dispatch an Event without EventDispatcherInterface injection boilerplate
  20. dispatch(new UpperCased($upper_case_str));
  21. return $upper_case_str;
  22. }
  23. }
  24. $dispatcher = new EventDispatcher();
  25. $dispatcher->subscribeTo(UpperCased::class, static function (UpperCased $event): void {
  26. echo "Some string was upper cased and it is: {$event->result}\n";
  27. });
  28. use_dispatcher($dispatcher);
  29. to_upper('dispatch');
  30. (new UpperCauser())->toUpper('rocks!');
  31. // Some string was upper cased and it is: DISPATCH
  32. // Some string was upper cased and it is: ROCKS!

Dispatchers

As said, this is only a small Facade on top of EventDispatcherInterface providing namespaced functions to reduce dispatcher injection boilerplate.

You still need a concrete implementation of an Event Dispatcher, anyone that implements the EventDispatcherInterface can be used, but here is a list of a few of them:

FAQ

Does it compromise my tests?

It shouldn’t. Unless you are testing that your module (class, function, method etc) is dispatching an Event, than it does not interfere the module’s behavior.

In case you want to test if the module is dispatching an Event.

And want to inject your fixture/stub/mock for EventDispatcherInterface, you can always just call use_dispatcher() in the test code or test setup.
The tricky part is that this dispatcher will be used globally all along.
But you can always call desuse_dispatcher() from your tests teardown.

Doesn’t it make my module dependency implicit?

Yes, it does. You have to think about dispatch() as like a PHP core/built-in function and as if event dispatching is a core part of your application. You model your domain on top of it.

But remember, it depends on EventDispatcherInterface only! It is an interface that can receive any concrete implementation and is a accepted and consolidated PSR interface.

Conclusion

Trade-offs you should accept to pay are:

  • The extra handling of the global EventDispatcherInterface on tests that should be isolated.
  • Vendor lock-in on this project as if it is a superset of PHP, since you will be not injecting interfaces.
    Unless you create your own dispatch() function under the Dispatch namespace (that is why this namespace name is so generic).

If these are ok to you. Happy coding! I’m sure it will make your event-driven apps pleasant to code with reduce boilerplate.

Inspired by