Injecting Custom Services

Summary

I’m having trouble trying to inject custom services into the dependency injection container for use with the modX::class. While I’m sure the documentation on this is enough for the more seasoned developers to understand, I’m barely catching up with this particular design pattern.

What I really need is a real life example of the bootstrap.php file. Does this file need to be in the root directory of our 3rd party component (i.e. core/components/newcomponent)? If I were to use the following:

\MODX\Revolution\modX::getLoader()->addPsr4('NewComponent\\', $namespace[MODX_CORE_PATH . 'components/newcomponent/model/newcomponent/'] . 'src/');

Am I using $namespace[] correctly? How would I access my service after the instantiation of MODx?

$modx->services->add('random_service', function($c) use ($modx) {
    return new NewComponent\RandomService($modx);
});

Is dot notation still usable with modX::addPackage or must we follow the namespace convention?

$modx->addPackage('NewComponent\\Model', $namespace['path'] . 'src/', null, 'NewComponent\\');

And since modX::getService() is now deprecated, how am I able to access these custom services once loaded in the container?

// Are they accessible from anywhere? 
$this->myService = new NewComponent\Services\MyService($this, $options[]);

// Like in a snippet without using modX::getService?
$myService = new NewComponent\Services\MyService($modx, $options[]);
if (!($myService instanceof NewComponent\Services\MyService)) {
    $err = 'An instance of MyService failed to instantiate!';
    $modx->log(modX::LOG_LEVEL_ERROR, '[NewComponent] ' . $err);
    return false;
}

// Or are we able to use them immediately?
$this->modx->random_service->serviceMethod('arg', true, false);
$myService = $this->random_service->randomMethod();

Please be as descriptive as possible. I’m here for the reading material.

Environment

I’m on the MODx Cloud running MODX Revolution 3.0.0-alpha2 (traditional).

Take a look at this example…

Does this file need to be in the root directory of our 3rd party component (i.e. core/components/newcomponent)?

Yes.

Am I using $namespace correctly?

No. See the example.

Is dot notation still usable with modX::addPackage or must we follow the namespace convention?

While it is usable for backward compatibility, it is recommended new components use proper PHP namespaces.

And since modX::getService() is now deprecated, how am I able to access these custom services once loaded in the container?

You can use the get() method on the container, e.g. $myService = $modx->services->get('random_service');

Just remember that $modx->services is just a PSR-11 compatible DI container. You can use it as you would a DI container anywhere, get()ing the “services” from it by the key you use to add() it to the container.

3 Likes