Yii 1.1 Application Development Cookbook
上QQ阅读APP看书,第一时间看更新

Using exceptions

Exceptions are a core PHP feature, but they are seldom used fairly. Yii makes exceptions very useful.

There are two main areas where Yii exceptions come in handy, which are as follows:

  1. Exceptions allow simplifying the process of detecting and fixing application errors and special situations, such as database connection failure or API failure.
  2. Exceptions allow generating different HTTP responses in a very clean way.

Generally, an exception should be thrown when a component cannot handle a special situation, such as the one said earlier, and needs to leave it to higher-level components.

How to do it…

  1. Let's assume that we have an application/apis/lyrics/LyricsFinder.php class that makes an HTTP request to an API using CURL and returns song lyrics based on its name. This is how we can use exceptions inside of it:
    // create some custom exceptions to be able to catch them
    // specifically if needed
    
    // general lyrics finder exception
    class LyricsFinderException extends CException {}
    
    // used when there is a connection problem
    class LyricsFinderHTTPException extends LyricsFinderException{}
    
    
    class LyricsFinder
    {
       private $apiUrl = 'http://example.com/lyricsapi&songtitle=%s';
    
       function getText($songTitle)
       {
          $url = $this->getUrl($songTitle);
          $curl = curl_init();       
          curl_setopt($curl, CURLOPT_URL, $url); 
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
          $result = curl_exec($curl);
    
          // if there is an HTTP error, we'll throw an exception if($result===false)
          {
             $errorText = curl_error($curl);
             curl_close($url);
             throw new LyricsFinderHTTPException($errorText);
          }
    
          curl_close($curl);
          return $result;
       }
       
       private function getRequestUrl($songTitle)
       {
          return sprintf($this->apiUrl, urlencode($songTitle));
       }
    }
  2. As we don't know how a specific application needs to handle its API connection, we will leave it to the application itself by throwing a custom LyricsFinderHTTPException. This is how we can handle it in our protected/controllers/TestController.php:
    class TestController extends CController
    {
      public function actionIndex($song)
      {
        $lyric = 'Nothing was found.';
        
        // importing api class
        Yii::import('application.apis.lyrics.LyricsFinder');
    
        $finder = new LyricsFinder();
    
        if(!empty($song))
        {
           // We don't want to show user an error.
           // Instead we want to apologize and
           // invite him to try again later.
           try {
              $lyric = $finder->getText($song);
           }
           // we are looking for specific exception here
           catch (LyricsFinderHTTPException $e)
           {
              echo 'Sorry, we cannot process your request. Try again later.';
           }
        }         
    
        echo $lyric;
      }
    }
  3. Another usage of Yii exceptions is the generation of different HTTP responses by throwing CHttpException. For example, an action that displays a blog post represented by a Post model, loaded by its ID will look like this:
    class PostController extends CController
    {
      function actionView()
      {
        if(!isset($_GET['id']))
          // If there is no post ID supplied, request is definitely wrong.
          // According to HTTP specification its code is 400.
          throw new ChttpException(400);
          
          // Finding a post by its ID
          $post = Post::model()->findByPk($_GET['id']);
          
          if(!$post)
             // If there is no post with ID specified we'll generate
             // HTTP response with code 404 Not Found.
             throw new CHttpException(404);
    
             //  If everything is OK, render a post
             $this->render('post', array('model' => $post));
      }
    }

How it works…

Yii converts all non-fatal application errors to CException automatically.

Additionally, the default exception handler raises either the onError or an onException event. The default event handler writes a log message with error level set to error. Additionally, if your application's YII_DEBUG constant is set to true, unhandled exception or error will be displayed at a handy error screen. This screen includes a call stack trace, a code area where the exception was raised, and the file and line where you can look for the code to fix.