miqrogroove
|
|
Service Container
Discussions about new features pointed to a need for a proper Service Container.
I added a very basic container in the 1.12-dev branch.
Now I have ChatGPT insisting service creation needs to be unlinked from service registration to allow for things like circular dependency detection
and lazy resolution of the services. I'm not convinced we need this yet.
Pros: Less manual tracking of dependencies. A laughable small performance boost if some of the services don't get resolved during each page hit.
Cons: Requires a factory for every service. Dependency injection is no longer procedural, looks more like OOP takes the wheel.
|
|
|
miqrogroove
|
|
Here's what this looks like with a factory for every service:
https://github.com/miqrogroove/xmb/commit/57b49bb7682c7f684e...
Notice I had to completely rewrite the include/Services/recipes.php file. The impact to other areas of the code base is not bad. I just wonder if
the future audience of XMB will get lost in this modern approach to service registration?
The next step for this is to add circular dependency detection to prevent infinite recursion mistakes in the container.
|
|
|
flushedpancake
Senior Member   
Posts: 178
Registered: 4-1-2024 Location: England
Member Is Offline
Mood: Fine, I suppose
|
|
I mean, from what I could make of it, it seems to make sense. In fact, I could see it being quite interesting from an extensibility perspective:
potentially, it makes it far easier to load in additional core services at runtime that could integrate with the board software seamlessly, in a
better way than a simple hacked-up plugin hook system (as previously proposed earlier) could. In terms of integrating with an existing website's
infrastructure this could be a major selling point for XMB, in fact.
Intrigued to see how it goes, especially with theoretical examples of practical purpose, as my understanding of modern PHP and software infrastructure
is extremely limited at best. However I'm absolutely open to adventurous, modern ideas, so y'know.
Website
Only takes one tree, to make a thousand matches, only takes one match, to burn a thousand trees...
|
|
|
miqrogroove
|
|
Passing the container into each factory is starting to look like a mistake, especially for recursion tracking. The more flexible approach will be for
each factory to accept a Closure. Then the container has a little more authority over what happens when the factory calls back for the dependencies.
|
|
|
miqrogroove
|
|
It works now. The test I used was to add a request for the core service inside the factory for the settings service. XMB logged this:
| Code: | [01-Nov-2026 19:59:13 America/Los_Angeles] PHP Fatal error: Uncaught XMB\Services\ContainerException: Circular dependency detected for service class XMB\Core in include/Services/Container.php:75
Stack trace:
#0 include/Services/Container.php(84): XMB\Services\Container->get('core', Object(XMB\Services\DependencyContext))
#1 include/Services/recipes.php(219): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('core')
#2 include/Services/Container.php(87): XMB\Services\create_settings(Object(Closure))
#3 include/Services/Container.php(84): XMB\Services\Container->get('settings', Object(XMB\Services\DependencyContext))
#4 include/Services/recipes.php(286): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('settings')
#5 include/Services/Container.php(87): XMB\Services\create_theme(Object(Closure))
#6 include/Services/Container.php(84): XMB\Services\Container->get('theme', Object(XMB\Services\DependencyContext))
#7 include/Services/recipes.php(301): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('theme')
#8 include/Services/Container.php(87): XMB\Services\create_bbcode(Object(Closure))
#9 include/Services/Container.php(84): XMB\Services\Container->get('bbcode', Object(XMB\Services\DependencyContext))
#10 include/Services/recipes.php(327): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('bbcode')
#11 include/Services/Container.php(87): XMB\Services\create_attach(Object(Closure))
#12 include/Services/Container.php(84): XMB\Services\Container->get('attach', Object(XMB\Services\DependencyContext))
#13 include/Services/recipes.php(342): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('attach')
#14 include/Services/Container.php(87): XMB\Services\create_core(Object(Closure))
#15 include/Services/Container.php(84): XMB\Services\Container->get('core', Object(XMB\Services\DependencyContext))
#16 include/Services/recipes.php(367): XMB\Services\Container->{closure:XMB\Services\Container::get():81}('core')
#17 include/Services/Container.php(87): XMB\Services\create_loader(Object(Closure))
#18 header.php(163): XMB\Services\Container->get('loader')
#19 admin/index.php(26): require('header.php')
#20 {main}
thrown in include/Services/Container.php on line 75 |
Stack entries #15 and #0 were identical, and we detected that as an infinite loop.
|
|
|