We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Correct way to edit a database service after first initiation

I use two different database services in my Phalcon application.

  • db: Global database with system-wide data, including accounts and users
  • db_data: This database hosts customer-specific data. The database-name is different for each customer/account. This is determined when the customer sign in.

This works in the web application, when I have one account active. Now I have a cronjob, that is going to loop through a table in the global "db" database. And after it is going to connect to the specific "db_data" database.

This works for the first account, but after this it will not connect to the new database. It still use the first initiated database.

The db_data service is a shared service in the services.php:

$di->set('db_data', function () use ($config, $di) {
        if(!$di->getCore()->getAccount()) {
                throw new \MyNamespace\Exception(_('Account is not set. Can not load account database.'));
        }
        $eventsManager = $di->getShared('eventsManager');
        $dbListener = new \MyNamespace\Module\Core\Helper\Model\DatabaseListener();
        $eventsManager->attach('db_data', $dbListener);
    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        'host' => $config->database->host,
        'username' => $config->database->username,
        'password' => $config->database->password,
        'dbname' => $config->database->data_dbname_prefix.$di->getCore()->getAccount()->id,
        'name' => 'data',
    ));
        $connection->setEventsManager($eventsManager);
        return $connection;
}, true);

In the first model in "db" i have the following in the initialize() function:

$this->setConnectionService('db');

In the second model in "db_data" i have the following in the initialize() function:

$this->setConnectionService('db_data');

Here is an example of the cron PHP-file:

$screens = \MyNamespace\Module\DigitalSignage\Model\Screen::find(array(
    'conditions' => 'deleted_at IS NULL',
));

foreach($screens as $screen) {
    $console->getDi()->getCore()->setAccount(\MyNamespace\Module\Core\Model\Account::findFirst('id='.$screen->account_id));
    $campaign = \MyNamespace\Module\DigitalSignage\Model\Campaign::findFirst(array(
            'conditions' => 'id = :id: AND account_id = :account_id: AND deleted_at IS NULL',
            'bind' => array(
                'id' => $screen->digitalsignage_campaign_id,
                'account_id' => $console->getDi()->getCore()->getAccount()->id,
            ),
        ));

    var_dump($campaign);
}

What is the correct way to change the database service parameteres after first initiation?

Phalcon version: 3.2.2 PHP version: 7.0.22



47.7k

I only have a suggestion/question.

Have you double checked your bootstrap?

What should I check for?

I think I will go for a PHP cronjob that spawn separate processes for each "account"/database. It is a bit more time- and resource consuming, but that will do the trick for me.

I have a colleague that checked the Zepire source code. And it seems there is a problem with PDO that can not change connection settings after first setup. Can someone confirm that this is correct?



11.9k

Did you try close the connection and recreate with new user account ?

I'm no so sure to renint old database connection with new account.