TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Changes to custom error handling in 3.3?
  • I have an error handler (try/catch) in my bootstrap.php that was working fine until a recent git pull from kohana/core 3.3/develop. (I have not been able to track down which commit it was that caused the problem.) Basically, an HTTP_Exception_404 that is thrown by a controller in my custom module is never caught by the catch in the bootstrap. I posted the question on StackOverflow, but I figured it might get more exposure if I post it here to. There are some code sample there: http://stackoverflow.com/questions/10727332/thrown-exception-not-caught-in-try-catch

  • Probably commit 1fcafa4b68a8a90a7100ff1512bc4645ceb15243 , which removed the throw $e from the code. If code no longer throws exceptions all the way back, how should custom error pages be done?

  • Closing the StackOverflow question, since this change appears to be the problem. Here is my code sample from there.

    bootstrap.php

    ...
    try {
        // Execute the main request
        $response = Request::factory()->execute();
    } catch (Exception $e) {
        // Code to show custom errors is here
    ...
    

    MyController.php

    ...
    public function action_throw_404()
    {
        throw HTTP_Exception::factory(404,
            'File not found: :file',
            array(':file' => $this->request->param('file'))
        );
    }
    ...
    

    init.php

    // This route will not be hit if the file exists.
    // It will cause a 404 if the file does not exist.
    Route::set('template/asset', 'assets/<file>', array(
            'file'      => '.*',
        ))
        ->defaults(array(
                'controller' => 'Errors',
                'action' => 'throw_404',
        ));
    

    Here is a stack trace:

    Kohana_HTTP_Exception [ 404 ]: File not found: assets/js/chosen.jquery.js
    
    APPPATH\classes\Controller\Errors.php [ 38 ]
    33     public function action_throw_404()
    34     {
    35      throw HTTP_Exception::factory(404,
    36              'File not found: :file',
    37              array(':file' => $this->request->param('file'))
    38          );
    39     }
    40 }
    
    SYSPATH\classes\Kohana\Controller.php [ 84 ] » Controller_Errors->action_throw_404()
        84      $this->{$action}();
    {PHP internal call} » Kohana_Controller->execute()
    SYSPATH\classes\Kohana\Request\Client\Internal.php [ 97 ] » ReflectionMethod->invoke()
        97          $response = $class->getMethod('execute')->invoke($controller);
    SYSPATH\classes\Kohana\Request\Client.php [ 114 ] » Kohana_Request_Client_Internal->execute_request()
        114         $response = $this->execute_request($request, $response);
    SYSPATH\classes\Kohana\Request.php [ 989 ] » Kohana_Request_Client->execute()
        989         return $this->_client->execute($this);
    APPPATH\bootstrap.php [ 71 ] » Kohana_Request->execute()
        69  try {
        70  // Execute the main request
        71  $response = Request::factory()->execute();
    DOCROOT\index.php [ 39 ] » require()
        39  require APPPATH.'bootstrap'.EXT;
    
  • I hope I understood this correctly, but the reason Kohana no longer bubbles exceptions out of the request is because requests should be isolated. For example, if you consume your own API from your application, things like Request::factory('api/users')->execute() should never throw an exception, it should simply return a response with the 500 or other appropriate response code. Wrapping your main request in a try/catch was never reliable because it only works with some exceptions. What you should be doing is replacing the default exception handler (by default, Kohana_Exception::handler()) with your new logic. Note that 3.3 also has a bunch of nice HTTP exceptions for things like 404 errors being triggered by controllers.

  • Right, the way you are doing hasn't been recommended since 3.0.

  • Ok, I am trying the 'new' way and I am having the following issue: It appears at the point that Kohana_Exception is first loaded, the modules have not been added to the path yet. Does this mean that it is not possible for a module to extend Kohana_Kohana_Exception, it can only be done in the application? I have 12 sites running off a single system and modules directory (the only difference is in the template in the application directory). Does this mean I will have to add the exception handler to each one?

  • I will split this off into its own topic so that it can get proper attention.

  • If I recall correctly, we did run into this limitation or something similar while talking on IRC and there isn't a good solution that I can think of other than to have it in the application folder. Personally, I think we need to change the order in which modules get included so that the files are all merged, then Kohana::init() is called, then all the module's init.php files are included. But this is something I want to talk about for 3.4 as it's far too late for any 3.3 changes.

  • If you merge the Kohana::modules() function into Kohana::init(), then you can set Kohana$_paths, then set the exception handler, then run the init.php for each module. That looks like ti should not be too hard to do, and you can leave the old Kohana::modules() in for backward compatibility.

  • Yeah, I would like to see something like that but it's not possible to do to 3.3, adding parameters is an API change and 3.3 is locked. This would be something you need to change in your copy in the meantime.

  • This is getting ahead of things, but I would be interested to know what you think of this solution. https://github.com/kohana/core/pull/268

  • That last one only appeared to work in specific circumstances. This one really works: https://github.com/kohana/core/pull/269

  • I have problem with error handlers. Sometimes Kohana uses Kohana_Exception::handler() sometimes not.

    I've extended main exception class like that:

     class Kohana_Exception extends Kohana_Kohana_Exception {
    
    public static function handler(Exception $e)
    {
        echo 'Kohana_Exception::handler';
        return parent::handler($e);
    }
    
    public static function _handler(Exception $e)
    {
        echo 'Kohana_Exception::_handler';
        return parent::_handler($e);
    }
    

    to test the behavior. I've noticed that there are 3 cases:

    1. No handler is called (mostly with HTTP_Exception)
    2. Only Kohana_Exception::_handler() is called.
    3. Both Kohana_Exception::handler() & Kohana_Exception::_handler() are called.

    Can someone explain me that?

  • HTTP exceptions should be handled as described in the documentation: http://kohanaframework.org/3.3/guide/kohana/tutorials/error-pages

    If you have generic, non-http exceptions you need to globally handle, you need to overload Kohana_Exception::_handler(). It does not use _handler() for http exceptions: https://github.com/kohana/core/blob/3.3/master/classes/Kohana/Request/Client/Internal.php#L105

  • zombor, or just overlod Kohana_Exception:reponse() ?

  • Well, just to note... Im migrating our codebase 3.2 to 3.3. The only thing missing is exception handling.

    We have a bigger deal cause we extended kohana a lot to support bigpipe (load stuff in chunks, inspired by facebook) and lots of other stuff.

    So, there is a problem that is the manual calls to Kohana_Exception::_handler in Kohana_Request_Client_Internal cause our registered custom exception handler is not called if i have an error inside a controller like a unset variable.

    So for now, to change the behavior of Kohana_Exception i would have to change the code directly, not using the HMVC... (something like https://github.com/yakatz/kohana-core/commit/4d63fcc25e7ef5c7de7925e48ecdf14389895d33) Is that correct?

  • @yakatz thx, your solution using Kohana_Exception_Starter did the tricky. It should be included in 3.4! Thx!

    https://github.com/yakatz/kohana-core/commit/4d63fcc25e7ef5c7de7925e48ecdf14389895d33

  • @Zeelot3k as for your comment on Exceptions not bubble, i agree with you. But we have a very special case where the Exception Handler tries to load an error controller to show nice error page. If the page is not found or has an exception (like a database exception) i wanna try another backup controller that has just a simple HTML. In this case i need the exception to bubble so my Exception Handler can detect it and call the backup controller. So i made the bubble of exceptions optional adding a method to the Request and modified the Request_Client_Internal to bubble if requested. This could be included in 3.4. Here is the commit: https://github.com/Meritts/core/commit/407c48acc59ec3dd4c80831540c3511e946374be

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion