Accessing Foreign MODX Tables

I’m trying to build a snippet that can access the pages from another MODX site on the same server without resorting to an RSS feed (I’ll eventually need to get more than just the resources).

I know how to connect to a foreign database successfully, but when I try to use getCollection on the external database connection to access MODX tables, I don’t get any data.

This works

$results = $external->query("SELECT id FROM modx_site_content");
$recordCount = $results->rowCount();
echo $recordCount;

This doesn’t

$resources = $external->getCollection('modResource');
echo '<pre>'.print_r($resources, true).'</pre>';

At the most basic level, is this even possible? If so, is anyone able to provide any guidance?

Maybe it’s a permissions issue. xPDO does permission checks when accessing data.

You cannot access MODX classes with an external xPDO connection. You would need a complete separate MODX instance with all of the configurations from the external site.

1 Like

What @opengeek said. The class you are referring to with getCollection(‘modResource’) isn’t defined within that $external xPDO reference.

I’ve never tried to initialize two separate instances of modX within a single script. That seems … messy. You could try something like

$external = new modX($dsn, $username, $password, $options);
$external->initialize('web');

Thanks for the direction. That makes sense. When I try that code though I get “Could not load MODX config file.”

$dsn = "mysql:host=$host;dbname=$dbname;port=$port;charset=$charset";

// require_once '/home/xxxxx/public_html/config.core.php';
$external = new modX($dsn, $username, $password);
$external->initialize('web');

echo $o = ($external->connect()) ? 'Connected' : 'Not Connected';

return true;

That code won’t work because you haven’t “included” the config.core.php and then config.inc.php files. But that’s not going to work because it would redefine the MODX constants. It might work if you can create a separate session or (probably better) do the includes and DB extraction in a processor, called through a connector, in a way that makes the original MODX instance not in scope.

TBH, I think you’re much better off giving up on using getCollection() and just writing queries that get you what you want.

Thank you guys for your help!

@bobray, I agree that it’s probably not worth using getCollection() in this case and I’ll just move on with writing the queries.

So after resorting to just writing the queries, I decided to try 1 more thing and it worked!

Ended up using CMPGenerator for foreign databases.

The tables I have in the settings are: modx_site_htmlsnippets, modx_site_snippets, modx_site_content, modx_site_templates, modx_site_tmplvar_contentvalues.

There aren’t any relationships created, but the resources can be accessed by using SiteContent (instead of modResource), chunks by using SiteHtmlsnippets (instead of modChunk), etc.

Here’s my final code:

$external = new xPDO($dsn, $username, $password);
$package_path = '/home/xxxxx/public_html/core/components/external/model/';

if (!$external->addPackage('external', $package_path, 'modx_')) {
    print 'There was a problem adding your package.';
}

// Test your connection
echo $o = ($external->connect()) ? 'Connected' : 'Not Connected';

// newQuery is needed along with selecting at least the id. Without this no data is provided.
$c = $external->newQuery('SiteContent'); 
$c->select('id');
$resources = $external->getCollection('SiteContent', $c);

foreach ($resources as $resource) {
    echo $resource->get('pagetitle').'<br/>';
}

$resources = $external->getCount('SiteContent');
$chunks = $external->getCount('SiteHtmlsnippets');
$snippets = $external->getCount('SiteSnippets');
$templates = $external->getCount('SiteTemplates');

echo "$resources Resources, $chunks Chunks, $snippets Snippets, $templates Templates";

The only issue at this point (that I’m aware of) is that I can’t seem to update objects on the foreign site. I can create objects, but updating fails for some reason. There are no errors.

For my purposes that’s fine as I’ll only need to read the data, but at least for now I think this’ll do. :smile:

Maybe, it would be a good idea to create a REST API or something on the foreign site, to access the data.

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”.