-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Apply inflectors right after the concrete is resolved #266
Comments
Container isn't really designed for what you're trying to do in the example.
`addMethodCall` is there to provide dependencies that need to be provided via a method call, and by extension, inflectors are there to make it so you can define method injection for many definitions of the same type.
If you have a better real world example then I'd be happy to continue the conversation but as it stands this is more an order of operations issue in the example code.
…-------- Original Message --------
On 30/11/2024 04:17, Arcesilas wrote:
I'm not sure the title is self-explanatory...
Since a picture is worth a thousand words, here is an example (with a few files):
class
Logger
{
public
function
log
(
string
$
message
):
void
{
echo
$
message
.
PHP_EOL
;
}
}
interface
LoggerAwareInterface
{
public
function
setLogger
(
Logger
$
logger
):
void
;
}
use
League
\
Container
\
ServiceProvider
\
AbstractServiceProvider
;
use
League
\
Container
\
ServiceProvider
\
BootableServiceProviderInterface
;
class
LoggerProvider
extends
AbstractServiceProvider
implements
BootableServiceProviderInterface
{
public
function
provides
(
string
$
id
):
bool
{
return
Logger
::class ===
$
id
;
}
public
function
register
():
void
{
$
this
->
getContainer
()->
add
(
Logger
::class);
}
public
function
boot
():
void
{
$
this
->
getContainer
()->
inflector
(
LoggerAwareInterface
::class)
->
invokeMethod
(
'
setLogger
'
, [
Logger
::class]);
}
}
class
Foo
implements
LoggerAwareInterface
{
private
Logger
$
logger
;
public
function
setLogger
(
Logger
$
logger
):
void
{
$
this
->
logger
=
$
logger
;
}
public
function
doSomething
():
void
{
$
this
->
logger
->
log
(
'
Doing something
'
);
}
}
use
League
\
Container
\
ServiceProvider
\
AbstractServiceProvider
;
class
FooProvider
extends
AbstractServiceProvider
{
public
function
provides
(
string
$
id
):
bool
{
return
Foo
::class ===
$
id
;
}
public
function
register
():
void
{
$
this
->
getContainer
()->
add
(
Foo
::class)
->
addMethodCall
(
'
doSomething
'
);
}
}
And a simple test script:
require
__DIR__
.
'
/vendor/autoload.php
'
;
$
container
=
new
Container
();
$
container
->
addServiceProvider
(
new
LoggerProvider
());
$
container
->
addServiceProvider
(
new
FooProvider
());
$
foo
=
$
container
->
get
(
Foo
::class);
This script gives the following error: PHP Fatal error: Uncaught Error: Typed property Foo::$logger must not be accessed before initialization
This happens because the inflector is not applied immediately when the concrete is resolved (in the Definition class), but much later, when the Container sends it. A workaround is to manualy call the setter in the boot() method of the Service Provider, but then the inflector becomes pointless.
Is it worth considering applying inflectors earlier (in Definition::resolveNew(), before `invokeMethods() is called, apparently) or is this behavior by design?
I personnally think it's worth considering (obviously), since when I invoke methods on an object reolved by the container, I expect it to be fully usable.
I've quickly tried something before opening this issue and it seems there is an infinite loop if we try to apply inflectors in Definition immediatly before the invokeMethods call...
—
Reply to this email directly, [view it on GitHub](#266), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/AAP3E2LFSW6D63DHPJCFMBT2DE37FAVCNFSM6AAAAABSYDEA7CVHI2DSMVQWIX3LMV43ASLTON2WKOZSG4YDMNRQGY4TONQ).
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Thanks for your quick answer! I understand what you mean. My use case was loading configuration file and wanted the logger to be ready in order to display information on the command line. Actually, I was configuring my app, not Container. This is why I got confused. Thanks again for your enlightening explanation as always! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm not sure the title is self-explanatory...
Since a picture is worth a thousand words, here is an example (with a few files):
And a simple test script:
This script gives the following error:
PHP Fatal error: Uncaught Error: Typed property Foo::$logger must not be accessed before initialization
This happens because the inflector is not applied immediately when the concrete is resolved (in the Definition class), but much later, when the Container sends it. A workaround is to manualy call the setter in the
boot()
method of the Service Provider, but then the inflector becomes pointless.Is it worth considering applying inflectors earlier (in
Definition::resolveNew()
, before `invokeMethods() is called, apparently) or is this behavior by design?I personnally think it's worth considering (obviously), since when I invoke methods on an object reolved by the container, I expect it to be fully usable.
I've quickly tried something before opening this issue and it seems there is an infinite loop if we try to apply inflectors in Definition immediatly before the invokeMethods call...
The text was updated successfully, but these errors were encountered: