Handle Stopped Database

Hello,

I’m trying to elegantly handle a case where the database server has been stopped.

I’m getting this error:

PDO::__construct(): [2002] Connection refused (trying to connect via tcp://127.0.0.1:3306)




395     protected function createPdoInstance()

396     {

397         $pdoClass=$this->pdoClass;

398         if(($pos=strpos($this->connectionString,':'))!==false)

399         {

400             $driver=strtolower(substr($this->connectionString,0,$pos));

401             if($driver==='mssql' || $driver==='dblib' || $driver==='sqlsrv')

402                 $pdoClass='CMssqlPdoAdapter';

403         }

404         return new $pdoClass($this->connectionString,$this->username,

405                                     $this->password,$this->_attributes);

406     }

With a stack trace as:


/Library/WebServer/Documents/yii/framework/db/CDbConnection.php(405): PDO->__construct("mysql:host=127.0.0.1;dbname=e", "per", "prs", array())

#1 /Library/WebServer/Documents/yii/framework/db/CDbConnection.php(356): CDbConnection->createPdoInstance()

#2 /Library/WebServer/Documents/yii/framework/db/CDbConnection.php(313): CDbConnection->open()

#3 /Library/WebServer/Documents/yii/framework/db/CDbConnection.php(291): CDbConnection->setActive(true)

#4 /Library/WebServer/Documents/yii/framework/base/CModule.php(372): CDbConnection->init()

#5 /Library/WebServer/Documents/yii/framework/base/CModule.php(86): CModule->getComponent("db")

#6 /Library/WebServer/Documents/cours/protected/components/dao/AuthenticationDao.php(20): CModule->__get("db") 

Any ideas would be greatly appreciated.

  • Glenn

Normally an exception which you can catch should be thrown here. I’ve submitted a fix: https://github.com/yiisoft/yii/pull/645

Thanks for the quick reply.

But based on the comments in the bug it has been closed and will not be fixed. :(

As a workaround you can override the method like this:




// protected/components/DbConnection.php


class DbConnection extends CDbConnection

{


   protected function createPdoInstance()

   {

      return @new $this->pdoClass($this->connectionString,$this->username,$this->password,$this->_attributes);

   }


}



Then in your config:




'db' => array(

   'class' => 'application.components.DbConnection',

),



Now you can handle the thrown CDbException with try-catch or you process it in a event-handler.

For the latter try this in config:


'onException' => function($event)

{

   if ($event->exception instanceof CDbException)

   {

      // $event->exception refers to the thrown CDbException, it also has a errorInfo property

      $event->handled = true; // We do not want to display the Yii exception view

      // Do something here. You could call Yii::app()->runController() for example

   }

},

Hope that helps.

Wow this is nice I will give it a try!

Thanks for taking the time to write it up. :)

No problem. Small error, you have to do


$this->attributes or $this->getAttributes() // since $this->_attributes is private