Skip to content
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

FuncService Resolves Deps Early #20

Open
XedinUnknown opened this issue Oct 12, 2023 · 3 comments
Open

FuncService Resolves Deps Early #20

XedinUnknown opened this issue Oct 12, 2023 · 3 comments

Comments

@XedinUnknown
Copy link
Member

XedinUnknown commented Oct 12, 2023

Usecase

FuncService is a convenient way to create a simple invocable service. One use-case for this is a function that retrieves some configuration at call time, which could help facilitate lazy loading. Let's say, I have a block that, when rendered on a page, must fetch some data from an API, and display it. To render, it needs some configuration that may not yet be available at application load time - because it has yet to be fetched; but it has no use for it before, and thus loading this configuration (e.g. from the API) must not happen until and unless the block renders. With the new ability to specify whole service definitions as dependencies, it could be as simple as:

[
    'my-block-service' => new Constructor(MyBlock::class, [
        new FuncService(['service-that-is-only-required-during-rendering'], fn(ServiceType $service): ServiceType => $service),
    ]),
];

class MyBlock
{
    /**
     * @param callable(): ServiceType $getServiceForRendering Retrieves the service that's necessary to render the block
     */
    public function __construct(protected callable $getServiceForRendering)
    {
        // Service is not yet loaded; only its "getter"
    }

    public function render()
    {
        $service = ($this->getServiceForRendering)();
        // Do something with the service, which is only retrieved during rendering
    }
}

The Problem

FuncService resolves dependencies when it is resolved, rather than when the callable it returns is invoked. This necessitates that service-that-is-only-required-during-rendering is available during MyBlock's initialisation, which is way before it is used, if ever.

Suggested Solution

Make FuncService resolve dependencies when invoked, rather than when it is resolved.

@mecha
Copy link
Member

mecha commented Oct 12, 2023

This is a valid use case. But I'd rather not change the current behavior of FuncService and instead create a new helper specifically for this task. It could even help reduce the verbosity of using FuncService by only requiring a service ID.

Something like this:

[
    'my-block-service' => new Constructor(MyBlock::class, [
        new LazyService('service-that-is-only-required-during-rendering')
    ]),
]

@XedinUnknown
Copy link
Member Author

That came to my mind, and LazyService is indeed a fitting name. However, the aspect of "when to resolve dependencies" seems very applicable to the existing FuncService as well.

How about adding a flag to the constructor of FuncService?

I'm pro adding LazyService as well, regardless. If FuncService is modified, maybe it can be used under the hood somehow.

@mecha
Copy link
Member

mecha commented Oct 12, 2023

Sure. Adding a flag to FuncService sounds good, as long as the default value of the flag retains the current eager behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants