Catching ALL db-related exception

Hi there,

Either I was searching wrong or this topic was not yet covered here.

I’m trying to figure out the best solution to catch all connections or queries to DB, to introduce my own error handler. Is it possible to have one piece of code for handling all connections / queries or should I write it in each parts that uses DB?

I thought that doing something like that (in Controller class, which extends CController and from which all my controller extends):


/**

 * Customized onBeginRequest for sending DB user ID and catching all DB-related exceptions

 */

public static function beginRequest()

{

    	try

    	{

            	if(Yii::app()->db->active)

            	{

                    	if(!Yii::app()->user->isGuest)

                    	{

                            	//Send current user ID to database...

                            	$sql = 'BEGIN LWWW.SetCurrentUser('.app()->user->id.'); END;';

                            	$rowCount = app()->db->createCommand($sql)->execute();

                    	}

            	}

    	}

    	catch (Exception $e)

    	{

            	throw new CHttpException(500, 'Internal server error: '.$e->getMessage());

    	}

}

will be enough. But it seems, it isn’t. For example, if I enter incorrect value to any of filters used in CGridView then I get exception displayed in standard Yii-way, not handled by my so-called error handler (defined above), i.e. - not formatted in the way I would like it to see.

Why not to use the action error, here you have the exception.

If the exception is of type CDbException, you will do what you have to so.

In this case you have no needs of change error handler.

Either I’m missing something or error action doesn’t do the trick. I have it defined (as it was in base Yii app upon which I built my project) but even so errors when connecting to DB are displayed not in this view but as a standard Yii exception. That’s why I decided to write own error handler, which code is presented above, in my initial post, but this again doesn’t do trick, as I wrote - because errors from for example CGridView filters are again displayed as normal Yii exception, not catched by my error handler…

Try removing Yii debug, in this case all error will be passed to the view error.

I’ll give it a try to see, if I have any difference or maybe if problem is lying somewhere else. Thanks. But, actually right know I have problems removing YII_DEBUG (setting it to False), erh! :[

Just remove the line


defined('YII_DEBUG') or define('YII_DEBUG',true);

From index.php

You can attach to CApplication::onException event. For example to simply suppress all db related exceptions, you can do this (in config, just add it to the array):




'onException' => function($event)

{

   if ($event->exception instanceof CDbException)

   {

      // true means, mark the event as handled so that no other handler will

      // process the event (the Yii exception handler included).

      $event->handled = true;

   }

},



You can do everything within the handler, i.e. accessing Yii::app() without problems.

Though this anonymous function example only works with PHP >= 5.3. Read here for other ways to do it.

The idea, you provided, seems to be great! :]

I do have PHP 5.3.1 but even so I’m using the older method of attaching onException event handler. In this current situation I declared public static function handleExeption($event) in my own System class and attached it in configuration, just like I did with onBeginRequest handler, i.e.: ‘onException’=>array(‘System’, ‘handleExeption’) in application’s configuration.

But I don’t know what to do next, when my private handler actually handles the exception? What code to use, to render results in system error view? I tried both $this->render (“Using $this when not in object context”) and Yii::app()->controller->render (“Call to a member function render() on a non-object”).

EDIT: I also tried throw new CHttpException, which I used in old approach (handling exceptions through onBeginRequest) but now it only outputs this as a bulk test (like I would use die()) without error view and page layout.

To make thing more clear, what I need. I want ALL exceptions (of all kinds and not matter whether YII_DEBUG is set to true or false) to be displayed on my system error view. And I need access to event / controller generating this view, to be able to steer, if stack trace is sent (debug mode) or not (production mode) to this view? If I’m not mistaken - in default implementation exceptions in debug mode are not rendered within system error view, which is, what I’m trying to avoid.

Any problems? I’m having the same problem here

Trejder, did you find an adequate solution here? I want to do the same thing. Thanks!

Emily

:mellow:

Emily,

I’m not working on this project any more and frankly I don’t remember it too good! :] But I do recall that using Y!!'s idea (extending CApplication::onException event) worked just as I wanted.

Cheers,

Trejder