Multiple Database connections needed (Mongo DB)

Permalink
Hi,

I started a new project with concrete5.7 and have referred to the docs for calling a new (external) db connection. The issue is that I am looking to query information from my mongo db on localhost but cannot over-ride my default mySQL connection. Is it going to be possible to connect to mongoDB running my concrete5 and mongo through localhost?
I must be just missing a step of calling up a driver name or something in the database.php file but I can't find any documentation, Muchos to anyone who can point me in the right direction.

 
Korvin replied on at Permalink Reply
Korvin
In concrete5.7, we have a new object named `DatabaseManager`. Its job is to sit around and hold onto various database connections.

Likely if you are using this as a one off, you can get by just using your own manager or binding your active connection to the `Application` instance using `\Core::instance`. If you'd rather use the DatabaseManager, pull down the doctrine mongodb library and follow these steps.

NOTE: Versions before 5.7.1.1 have a bug that makes it so that you cannot add a connection that isn't a DBAL connection, for 5.7.1 read my second reply.

To add a mongodb connection, you must add an extension closure that builds the connection object since it's not a standard dbal connection:

In `/application/bootstrap/app.php` ADD:
use Doctrine\MongoDB\Connection;
\Database::extend('local_mongo', function($config, $name) {
    $client = new \MongoClient();
    return new Connection($client);
});


This gives us a constructor for our connections. Now we can add the configuration entry that describes it.

in `/application/config/database.php`, add a connection named "mongodb":
<?php
return array(
  'default-connection' => 'concrete',
  'connections' => array(
      'concrete' => array(
            ...
      ),
      // New local mongodb connection
      'mongodb' => array(
          'driver' => 'local_mongo'
      )
  )
);


Now you're done. Just use `\Database::connection('mongodb')` to get your active mongodb connection!
Korvin replied on at Permalink Reply
Korvin
IF YOU ARE ON ANY VERSION HIGHER THAN 5.7.1, THE FOLLOWING DOES NOT APPLY TO YOU!


In 5.7.1 and lower, we have a bug that prevents this from working since our class was previously tightly coupled to DBAL. In order to fix this, we must override the `DatabaseManager` class and remove the typehint (https://github.com/concrete5/concrete5-5.7.0/commit/50fb409af5cee354... )

First create a directory to hold these overrides, `/application/src/Database` (Case sensitive)

In `/application/src/Database/DatabaseManager`:
<?php
namespace Application\Src\Database;
class DatabaseManager extends \Concrete\Core\Database\DatabaseManager
{
    protected function prepare($connection)
    {
        return $connection;
    }
}


Now that we have removed the type hint, we have to make sure that we use OUR `DatabaseManager` object rather than the core's, to do that we'll need to override the database service provider and make sure that it references ours instead.

In `/application/src/Database/ServiceProvider`:
<?php
namespace Application\Src\Database;
use Concrete\Core\Database\Connection\ConnectionFactory;
use Concrete\Core\Database\DatabaseServiceProvider;
use Concrete\Core\Database\Driver\DriverManager;
class ServiceProvider extends DatabaseServiceProvider {
    public function register()
    {
        $this->app->bind(
            'database',
            function ($cms) {
                $driver_manager = new DriverManager($cms);
                $driver_manager->configExtensions(\Config::get('database.drivers'));
                $factory = new ConnectionFactory($cms, $driver_manager);
                return new DatabaseManager($cms, $factory);



(If you are not on 5.7.1, you will need to be for this.)
The last thing is to tell the core to use our new service provider. To do that, we need to override the configuration entry.

In `/application/config/app.php`:
<?php
return array(
    'providers' => array(
        'core_database' => 'Application\Src\Database\ServiceProvider'
    )
);


That's it, now you should be good to go!