简体   繁体   中英

Too many connection when extending Phalcon\Db\Adapter\Pdo\Mysql

I've attempted to extend the Phalcon\\Db\\Adapter\\Pdo\\Mysql to create a log every time a query function returns false .

Even though I'm not creating any new connections except the one in parent::__construct I'm getting the following exception:

Fatal error: Uncaught PDOException: SQLSTATE[08004] [1040] Too many connections in ...Internal/Database/Mysql.php:14 Stack trace: #0 [internal function]: PDO->__construct('mysql:adapter=M...', '...', '...', Array) #1 [internal function]: Phalcon\Db\Adapter\Pdo->connect(Array) #2  .../Internal/Database/Mysql.php(14): Phalcon\Db\Adapter\Pdo->__construct(Array) #3 .../apps/bootstrap/app.php(378): Internal\Database\Mysql->__construct(Array) #4 [internal function]: Closure->{closure}() #5 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #6 .../apps/bootstrap/core_services.php(7): Phalcon\Di->get('logs') #7 [internal function]: Closure->{closure}() #8 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #9 .../apps/libs/Internal/Database/Mysql.php(15): Phalcon\Di->get('logger') #10 .../apps/bootstrap/app.php(37 in .../apps/libs/Internal/Database/Mysql.php on line 14

Code:

namespace Internal\Database;

use Phalcon\Db\Adapter\Pdo\Mysql as PhalconMysql;
use Phalcon\Di;

class Mysql extends PhalconMysql
{
    public $isLogger = false;

    public function __construct(array $descriptor)
    {
        parent::__construct($descriptor);
        $this->oLogger = Di::getDefault()->get('logger');
    }

    public function query($sqlStatement, $bindParams = null, $bindTypes = null)
    {
        $oResult = parent::query($sqlStatement, $bindParams, $bindTypes);
        if ($oResult === false && $this->isLogger === false) {
            $trace = debug_backtrace();
            $aCaller = array_shift($trace);
            $sFile = $aCaller['file'];
            $sLine = $aCaller['line'];
           $this->oLogger->error('MySQL query failed. File: ' . $sFile . ', Line: ' . $sLine, ['error' => $this->getErrorInfo()]);
    }
        return $oResult;
    }
}

The line that triggers the error is parent::__construct($descriptor); .

The only other change I've made was to replace the usage of Phalcon\\Db\\Adapter\\Pdo\\Mysql with Internal\\Database\\Mysql . All the connections are created in the same way they were when I were using Phalcon\\Db\\Adapter\\Pdo\\Mysql .

I've looked at the parent classes of Phalcon\\Db\\Adapter\\Pdo\\Mysql . The only place I see the connection created is here

I'd very much appreciate your help with this issue.

It is not a right thing to extend classes in phalcon, that are actually interacting with other php extensions. Learned it the hard way.

The easy way I would recommend is to override Mvc/Model class as a eg. ModelCommon or BaseModel, and implement there Model::initialize and Model::afterFetch .

But a proper way would to be to use event mechanism developed out in Phalcon. The trick is to attach to beforeQuery and/or afterQuery events.

Shortcut for that, done in DI:

$di->set('db', function() use ($di) {
    $config = $di->getConfig();
    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql([
        // ...
    ]);

    $eventsManager->attach('db', function($event, $connection, $params) use ($config) {

        if ($event->getType() == 'beforeQuery') {
            // ...
        }

        if ($event->getType() == 'afterQuery') {
            // ...
        }
    });

    $connection->setEventsManager($eventsManager);
    return $connection;
});

Looks like the module is trying to connect to database more than once. Perhaps make sure you initialise database service just once in your Module.php

Maybe you can db service as shared when you declare db in $di

$di->setShared('db', function() {
    // return your db instance
});

Problem solved, although I still don't understand why it occurred in the first place.

The logger logs to the database, but since it's taken from Di I assumed it reuses existing connection. Removing that line from constructor, and putting it right after the logger is called solved the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM