MODX 3: bootstrap.php from an extras core/components path also included when loading MODX externally?

Is the MODX 3 bootstrap.php (from an extras core/components path) also included when MODX is loaded externally?

I’m asking because I can’t get a bootstrap build script (to build a dev environment from git source) to work. MODX is loaded but the service for my add-on isn’t found.

Here is the folder structure from my add-on:

This is how I load MODX externally (in _bootstrap/index.php):

use MODX\Revolution\modX;
use ...
use GoodNews\GoodNews;

require_once $sources['root'] . 'config.core.php';
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = new modX();

This is the content of my bootstrap.php (in core/components/goodnews):

$modx->addPackage('GoodNews\Model', $namespace['path'] . 'src/', null, 'GoodNews\\');
$modx->services->add('goodnews', function($c) use ($modx) {
    return new GoodNews\GoodNews($modx);
});

This is the service call in my bootstrap build script:

$goodnews = $modx->services->get('goodnews'); // <- this should work if bootstrap.php is executed!

Results in the following PHP error:

[04-Dec-2022 14:08:56 Europe/Vienna] PHP Fatal error:  Uncaught MODX\Revolution\Services\NotFoundException: Dependency not found with key goodnews. in /Users/xxxxxx/ProjekteWEB/modx.dev/modx3/core/src/Revolution/Services/Container.php:34
Stack trace:
#0 /Users/xxxxxx/ProjekteWEB/modx.dev/projects/goodnews/_bootstrap/index.php(135): MODX\Revolution\Services\Container->get('goodnews')
#1 {main}
  thrown in /Users/xxxxxx/ProjekteWEB/modx.dev/modx3/core/src/Revolution/Services/Container.php on line 34

I completely followed the working model from Articles add-on but without success!

Yeah, that’s also loaded automatically in that scenario. I don’t think it should be necessary but can you try adding $modx->initialize(‘mgr’); to your bootstrap?

Oh actually, make sure your namespace (modNamespace) is correct and has the core path set to the directory your bootstrap.php is in. Maybe that’s the missing link?

This is already present.

The add-ons namespace is not yet available at the time I try to get the goodnews service. This is also the case in Articles add-on.

Do I need to set the add-ons namespace before calling the goodnews service?
But if so, why does it work in Articles?

$modx->log(modX::LOG_LEVEL_INFO, 'Adding namespace...');
if (createObject($modx, modNamespace::class, array(
    'name' => PKG_NAMESPACE,
    'path' => $sources['source_core'],
    'assets_path' => $sources['source_assets'],
), 'name', false)) {
    $modx->log(modX::LOG_LEVEL_INFO, '-> added namespace: ' . PKG_NAMESPACE);
} else {
    $modx->log(modX::LOG_LEVEL_ERROR, '-> namespace ' . PKG_NAMESPACE . ' could not be added.');
    $modx->log(modX::LOG_LEVEL_INFO, 'Building development environment failed!');
    flush();
    exit();
}

This is how Articles bootstraps it’s dev environment:

Yes.

No idea. Maybe it doesn’t, but if the namespace was already there when they worked on upgrading that to 3.0 it didn’t have to?

Just moving the modNamespace creation up to before the $modx->services->get() should help. It would still error out the first time you call it. But work fine the second time.

Thanks Mark, I will try this although it is not a clean solution.

So - same error if I create namespace first :frowning:

If this is all part of one process, you may have to clear the cache after creating the namespace. Are you creating the modExtensionPackage object as well? I think that’s where MODX gets the namespace name and possibly the path, which takes this form in the modExtensionPackage object:

[[++core_path]]components/classextender/

OK, last but not least I had to realize that including the bootstrap.php of the component is useless in my case.

This is how I do it now:

/* Define package name and namespace */
define('PKG_NAME', 'GoodNews');
define('PKG_NAMESPACE', strtolower(PKG_NAME));
$className = PKG_NAME . '\\' . PKG_NAME;

...

require_once $sources['root'] . 'config.core.php';
require_once MODX_CORE_PATH . 'vendor/autoload.php';
require_once $sources['includes'] . 'functions.php';

/* Load MODX */
$modx = new modX();
$modx->initialize('mgr');
if (!$modx->services->has('error')) {
    $modx->services->add('error', function($c) use ($modx) {
        return new modError($modx);
    });
}
$modx->error = $modx->services->get('error');
$modx->setLogLevel(modX::LOG_LEVEL_INFO);
$modx->setLogTarget('ECHO');

...

/* Add package */
if ($modx->addPackage(PKG_NAME . '\Model', $sources['source_src'], null, PKG_NAME . '\\')) {
    $modx->log(modX::LOG_LEVEL_ERROR, PKG_NAME . ' package added.');
} else {
    $modx->log(modX::LOG_LEVEL_ERROR, PKG_NAME . ' package could not be added.');
    $modx->log(modX::LOG_LEVEL_INFO, 'Building development environment failed!');
    flush();
    exit();
}
flush();

/* Add package service */
if (!$modx->services->has(PKG_NAMESPACE)) {
    $modx->services->add(PKG_NAMESPACE, function($c) use ($modx, $className) {
        return new $className($modx);
    });
}
$service = $modx->services->get(PKG_NAMESPACE);
if ($service instanceof $className) {
    $modx->log(modX::LOG_LEVEL_ERROR, PKG_NAME . ' service loaded.');
} else {
    $modx->log(modX::LOG_LEVEL_ERROR, PKG_NAME . ' service could not be loaded.');
    $modx->log(modX::LOG_LEVEL_INFO, 'Building development environment failed!');
    flush();
    exit();
}
flush();

Works perfectly and without any deprecation logs.

Btw, thanks for your help guys!

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.