Closed lubobill1990 closed 4 years ago
That was done by @yiiliveext on purpose to deny adding event handlers at runtime. It still can be done via friendly classes (the ones extending from AbstractProvideConfigurator).
Do you have a use case where it's not desirable?
@yiiliveext
I'm confused by the example, why the attach
method can be called here if it's protected in Yiisoft\EventDispatcher\Provider\Provider
?
That was done by @yiiliveext on purpose to deny adding event handlers at runtime. It still can be done via friendly classes (the ones extending from AbstractProvideConfigurator).
I regard Yiisoft\EventDispatcher\Provider\Provider can be used independently in any project, if the attach
function is protected and Provider
is final, how can I use the Provider
class?
My use case is,
Yiisoft\EventDispatcher\Provider\Provider
as singleton at bootstrap.phpload.php
to the same directory of composer.json of my project composer packages"bootstrap": "ZhiShiQ\\Yii\\AppLoader"
to composer.json at extra
entryload.php
in the AppLoaderProvider
to load.php
, and listen to events for that packageWith this method, I can encapsulate event listening code inside the package.
I'm confused by the example, why the attach method can be called here if it's protected in Yiisoft\EventDispatcher\Provider\Provider?
Because it's a friendly class extended from the same base abstract class.
So I have to first make a class extending AbstractProvideConfigurator, then am able to call attach
in that class. It's too sinuous and preventing people from using this... We should have a balance between standard and flexibility.
And why it's so important to deny adding event handlers at runtime? To support swoole?
In general, attaching events in runtime (except initialization) usually results in unpredictable and problematic behavior of the code so that was an attempt to prevent people doing potentially harmful thing by allowing to attach events from config only.
I totally agree that it's way less straightforward during initialization because of that but I'm afraid that if we'll not disallow doing it explicitly there will be lots of code doing exactly that even if we'll state in the guide that it should not be done.
One of the purposes that we split yii2 to packages and develop yii3 is we hope every part of yii3 is valuable, people can adopt one sub package to their project rather than have to use the whole ecosystem. Currently, it seems that we change the event dispatcher package because of the way we use in other yii3 packages.
Even though people may make mistakes if they attach events after initialization, which can be debugged easily and we can also document it to help, we can't totally disable them to do, because there are indeed such scenarios, and force user to extend AbstractProvideConfigurator restricted their implementation too much, and make this package unpopular. (I think the current package is fairly good, potential to be popular, light wight and usable.)
In my previous example, I event don't use a class to bind the events, but event listenings are all defined in a load.php
which is called when application bootstrapped and is a standard in my project.
I hope the attach function can be made public again.
So I have to first make a class extending AbstractProvideConfigurator, then am able to call
attach
in that class. It's too sinuous and preventing people from using this... We should have a balance between standard and flexibility. And why it's so important to deny adding event handlers at runtime? To support swoole?
If you want to make this method public, you can do something like that
class MyProvider extends Provider
{
public function attach(callable $listener, string $eventClassName = ''): void
{
parent::attach($listener, $eventClassName);
}
}
Only seven lines of code and you have Provider with the public attach()
method.
So I have to first make a class extending AbstractProvideConfigurator, then am able to call
attach
in that class. It's too sinuous and preventing people from using this... We should have a balance between standard and flexibility. And why it's so important to deny adding event handlers at runtime? To support swoole?If you want to make this method public, you can do something like that
class MyProvider extends Provider { public function attach(callable $listener, string $eventClassName = ''): void { parent::attach($listener, $eventClassName); } }
Only seven lines of code and you have Provider with the public
attach()
method.
But Provider is final
which can't be extended.
Any news?
In fact, before this, I never knew protected can be called in sibling class. In most resources, portected is described as accessible from children and ancestors.
I believe most other developers will regard it as strange trick.
I searched and find this: https://wiki.php.net/rfc/protectedlookup
It seems it's somewhat a bug.
@lubobill1990 so nope, the "friendly classes" behavior we're using is normal won't be removed from PHP.
That's still controversial but @romkatsu finally added it to readme :)
No problem, I worked around this problem by replacing Dispatcher and Provider with customized Dispatcher and Provider which extends from AbstractProviderConfigurator and works as proxy to original Dispatcher and Provider.
Decided to keep it as is for a while.
Trying alternative approach in #22.
https://github.com/yiisoft/event-dispatcher/commit/680194bad114f1516d3ca9f8ea52807992ccc507#r38900256
What steps will reproduce the problem?
n/a
What is the expected result?
The attach function should be public anyway.
What do you get instead?
I can't call it any more from my project code.
Additional info