Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Error handling question (v.1.0)
  • 1) Is there a method like codeigniter's show_error() which will load an error view file and which stops the execution of a method? 2) I use a lot of REST-Controllers, so it would be nice to send JSON/XML/...-error messages in the error views. How can i check if the request was made to a Rest controller in the error view file? How can I check the detected format ($format) of Rest_Controller in the error view? Greetings,
    Matthias
  • No, there isn't. But
    $this->response->body = View::factory('errors/mine');
    return;
    
    will do the trick quite nicely. Note that CodeIgniter has a pretty straitforward front-to-back flow, so you can easily break out and stop. Fuel is more event driven, the fact that you stop a controller from execution doesn't stop everything around it (although this works fine for a main request). If you feel an extension of the error class is needed, please create a feature request at http://github.com/fuel/core/issues, explaining your reasons for wanting this feature.
  • Actually there is this option as well:
    throw new Request404Exception();
    

    There is also Request::show_404() for the same thing, but that will be deprecated in v1.1 and removed in the next.
  • Hmm... Considering the remark about CI's show_error(), I think the TS wants something that terminates the script, *like* a 404 exception, but with a view of his choice. What you could do is
    throw new Request404Exception('views/this/that');
    

    and then in your public/index.php
    // Generate the request, execute it and send the output.
    try
    {
     $response = Request::factory()->execute()->response();
    }
    catch (Request404Exception $e)
    {
     if ($e->getMessage() == '')
     {
      if ($route = Config::get('routes._404_'))
      {
       $response = Request::factory($route)->execute()->response();
      }
      else
      {
       throw $e;
      }
     }
     else
     {
      $response = new \Response(\View::factory($e->getMessage()), 500);
     }
    }
    

    Just make sure that view exists...
  • Will be possible a lot more gracefully in v1.1 thanks to the new support for a handle() method in Exception classes.
  • hmm... did I miss anything? Ah, change in the Error class. So the route is to define a custom exception that has this method, and then throw it? This seems to work:
    <?php
    class ApplicationException extends Exception {
    
     /**
      * Process the application error
      *
      * @return  void
      */
     public function handle()
     {
      ob_end_clean();
      echo \View::factory('errors/application', array('exception' => $this), false);
     }
    }
    

    Store this in app/classes/applicationexception.php. The view would be something like:
    <?php
    if ($m = $exception->getMessage())
    {
        echo $m;
    }
    else
    {
        echo "Put a generic error message here";
    }
    

    Then in your code you can use
    throw new ApplicationException('any message you want to pass');
    
  • Thanks for the example code, that is a nice and robust way to handle errors! But this is only for 1.1 with handle()-support in exceptions? (I tested it with 1.0 and handle() was not called when I threw an ApplicationException) Is there a quick way for doing the same in 1.0 or should I just override the error-
    class and change the things I need?
  • This is indeed 1.1 only. For 1.0, you could still throw the exception, and capture it in your index.php using a try/catch (see the 1.1 version of the index.php for an example). That way it will make the transition into 1.x easier as well...
  • Okay I've got it working the following way: public/index.php:
    //$response = Request::factory()->execute()->response();
    /* FROM 1.1 */
    // Generate the request, execute it and send the output.
    try
    {
     $response = Request::factory()->execute()->response();
    }
    catch (Request404Exception $e)
    {
     if ($route = Config::get('routes._404_'))
     {
      $response = Request::factory($route)->execute()->response();
     }
     else
     {
      throw $e;
     }
    }
    /* BY PROGRAMMIERAFFE */
    catch (ApplicationException $e)
    {
        $response = ApplicationException::handle($e);
    }
    /* EO BY PROGRAMMIERAFFE */
    /* EO FROM 1.1 */
    

    /fuel/app/classes/applicationexception.php:
    <?php
    class ApplicationException extends Exception {
     /**
      * Process the application error
      *
      * @return  response
      */
     public function handle($e)
     {
      ob_end_clean();
      return new \Response(\View::factory('errors/application',array('exception' => $e),false), 500);
     }
    }
    
    

    Feel free to optimize, I think it's not the most elegant / best method? And there is one error notice, because I called ob_end_clean in my error handler.
    ErrorException [ Notice ]: ob_end_flush() [ref.outcontrol]: failed to delete and flush buffer.
     No buffer to delete or flush.
    

    Edit: btw when you edit a post the forum software replaces "{" with the html code...
  • You can avoid the notice by using
    // only clean the buffer if it has any data in it
    ob_end_length() and ob_end_clean();
    
  • Thanks, that worked! Has somebody a quick hint for me how I can recognize the following in my handle() method:
    - was the request routed to a rest_controller ? (then i want to show a json/xml error)
  • I don't know of an easy way to find that out. But since you're triggering the error yourself by throwing the exception, you could pass something in the error message, or use the error code, to indicate what it is?
    // throw a normal text error
    throw new ApplicationException('this is a standard error');
    
    // throw a json text error
    throw new ApplicationException('this is a standard error', 1);
    

    You can access the code you pass using the exception object's getCode() method.

Howdy, Stranger!

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

In this Discussion