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
Containerization of services #16569
Containerization of services #16569
Conversation
Не должно быть никакого |
Я сперва так и сделал
Но phpunit тесты сделаны видимо не совсем правильно Возможно я не совсем верно упомянул о singalton, все таки это абстракция |
@@ -525,7 +525,8 @@ protected function loadConfig($configPath = '', $data = [], $driverOptions = arr | |||
include_once MODX_CORE_PATH . 'include/deprecated.php'; | |||
} | |||
|
|||
$container = new Container(); | |||
$container = Container::setInstance(new Container()); | |||
$container['modx'] = $this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modX is the app and you would never want this in the container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate the contribution, but I do not see the need for this. I am not a fan of Laravel-style static helper methods like this, and you can get the container from the modX app instance.
The problem I encountered is that every time I create a new class, I need to pass an instance of $modx to the constructor. This is inconvenient and leads to code duplication because I have to repeat this process for each class. One way to solve this problem is by using a dependency injection container. The dependency injection container allows you to create and store object instances and provide them when needed. Here's a simple example of how you can use a dependency injection container to solve the problem: class modX
{
public function getOption($name)
{
return 'http://site.com';
}
}
class Container
{
private static $instances = [];
public static function getInstance($className, $modx = null)
{
if (!isset(self::$instances[$className])) {
self::$instances[$className] = new $className($modx);
}
return self::$instances[$className];
}
}
class MyClass
{
private $modx;
public function __construct($modx)
{
$this->modx = $modx;
}
public function doSomething()
{
return $this->modx->getOption('site_url');
}
}
// Example usage:
$modxInstance = new modX(); // Creating an instance of $modx
$myClass = Container::getInstance('MyClass', $modxInstance);
echo $myClass->doSomething() . PHP_EOL;
// Later usage without modx instance
$myClass = Container::getInstance('MyClass');
echo $myClass->doSomething() . PHP_EOL; Now you can create just one instance of $modx and use it in any class whenever necessary, without the need to pass it to the constructor every time. To call a class without passing an instance of $modx to the constructor, you can use a static method, as in your example: class App {
public function getMsg()
{
return modX::getInstance('modX')::getOption('site_name');
}
} This Currently, it works like this, for example, I created 10 classes: class App {
public function __construct(modx $modx)
{
$this->modx = $modx;
}
....
}
class App2 {
public function __construct(modx $modx)
{
$this->modx = $modx;
}
....
}
class App3 {
public function __construct(modx $modx)
{
$this->modx = $modx;
}
....
}
class App4 {
public function __construct(modx $modx)
{
$this->modx = $modx;
}
....
} I don't see the point of duplicating this code, but at the moment, it's necessary. Wherever we create a new class, we must always include class App {
public function __construct(modx $modx)
{
$this->modx = $modx;
}
public function app2()
{
# Or return new AppCustom($this)
return new AppCustom($modx)
}
}
class AppCustom {
# or public function __construct(App $app)
public function __construct(modx $modx)
{
# or $this->app = $app;
$this->modx = $modx;
}
public function title()
{
# or return $this->app->modx->getOption('site_name')
return $this->modx->getOption('site_name')
}
} Considering full-fledged development through PSR-&, this is clearly pointless code duplication. When the whole world is already using containerization. |
Currently, there is no method in modx to call like this: Although you can achieve this through:
Naturally, this approach will require modification of index.php.
It works excellently, even with highly loaded projects, without causing any issues anywhere. following the example from @sergant210 , implemented this method in many projects and followed it for about two years, observing the problems that modY::getInstance('modY') can cause. Have not found It is clear that no one will change index.php Perhaps I didn't notice something, please give at least a code example when containerization for which the pull request was created will cause a problem? Tests passed. |
In my opinion, it is obvious that simplifying access to the application improves productivity. There is currently no reason not to accept this pull request. This code will not harm a simple user, but for professional development there will clearly be an increase. |
Modifying the index.php to call modX::getInstance() would solve the only problem you are trying to solve here, and I do not see any negative impact by changing the existing calls to the constructor to getInstance for this purpose. I would happily consider merging a PR that introduces this improvement. Creating redundantly nested instances of the app and container is not going to happen, though. All this said, using modX::getInstance() inside classes that depend on the modX application is not proper design. |
What does it do?
added the ability to call containers from any part of the code without the need to connect an instance with modx
Why is it needed?
Describe the issue you are solving.
The main feature is the full use of the composer without the need to additionally pass an instance of $modx to the class
In the future, you can simplify the call to modx through the function
Works similarly in Laravel
https://packagist.org/packages/illuminate/container
does not cause any problems
the code was taken from illuminate/container,
https://github.com/illuminate/container/blob/a0796471eff9649592d7b5bdc8f705c134ceaaac/Container.php#L1407
is a public singleton pattern
How to test
Tested the web interface and with using the code above
phpunit tests via Github Actions completed successfully
Related issue(s)/PR(s)
Have not found