Krillz.com

A coder’s steps revealed


Search



This is the second part of Buffering www applications with php that can be found here: buffering-www-applications-with-php

Buffering a www page using exceptions

Now let’s assume that our script would get the information from somewhere else like a database or a file that changes and after a time an error occurs on the page.
Which messes up the site and instead we see a lot of error messages, the visitor sees a lot of errors from the database instead of the content.
This scenario isn’t nice but thankfully we can avoid this situation if we use exceptions together with the page buffering. In this way we can catch the errors and instead display a page with our custom error messages and not the original ones that could give away crucial information to a potential hacker.
Fist of you should take a look at the Exception class below, so you better understand how our class will work later.

/*
Exception class - not complete!
*/

class Exception{
 
  protected $message = ‘Unknown exception’;
  protected $code = 0;
  protected $file;
  protected $line;
  private $trace;
  private $string;
 
  function __construct(string $message=NULL, int $code=0){
 
    if (func_num_args()) { $this->message=$message; }
   
    $this->code = $code;
    $this->file = __FILE__;
    $this->line = __LINE__;
    $this->trace = debug_backtrace();
    $this->string = StringFormat($this);
   
    }
   
   final function getMessage() { return $this->message; }
   final function getCode() { return $this->code; }
   final function getFiler() { return $this->file; }
   final function getTrace() { return $this->trace; }
   
   function __toString() { return $this->string; }
   
   …
   
 }

As you can see in the code above the Exception class has all of its functions declared as final so we cannot alter or define them differently in a child class.
But we can use one function that we can define differently in our child class ant that is __toString() and in our case this is just in that way we will alter our form of our communication.
We will do so when declaring our class PageError which will extend Exception that you can see in the code below.

/*
Declaration of the PageError class
*/

class PageError extends Exception {

  public function construct($message) { parent::__construct($message); }
  public function __toString() { return $this->template($this->getMessage());}
 
  protected function template ($only_message) {
   
    return ‘<html><body>’.$only_message.‘</body></html>’;
   
  }
 
}

In our declaration we also use another function, template, in which we will store the template of our site being the communication.
Doing it this way will mean that it will be a lot easier for us to later edit the layout of the page.

Next we call our function template() with the argument $this->message in the function __toString(), doing it this ways when errors occur or in other words exceptions arise our page will be displayed anyway.

Now it’s time to write the main script to our page, imagine that this page’s task is to display
iformation that has been formated from the database.
We won’t care about what it is getting from the database so all the problems that could occur we simply don’t give a damn about right now.
As we will catch the potential problems using a try and catch block.
Take a look at the code below:

<?php

include_once(‘class_page_error.php’);

function show_error($message) {
  ob_end_clean();
  throw new PageError($message);
 
  }
try {

  ob_start();
  ?>
 
  <HTML>
  <BODY>
  <?php
 
  if (!$db = mysql_connect(‘localhost’, ‘username’, ‘password’)){
    show_error(‘Couldn\’t connect to the database’);
    }
   
  if (!@$mysql_select_db(‘dbName’)){
    show_error(‘Couldn\’t select the database’);
    }
   
  if (!$request = mysql_query(’select * from table_name’,$db)){
    show_error(‘Error during query’);
    }
   
   ?>
   
   <TABLE><tr><td>key</td><td>Value</td></tr>
   
   <?php
   
   while ($row=mysql_fetch_assoc($request)){
    foreach ($row as $key => $value){
      echo “<tr><td>$key</td><td>$value</td></tr>”;
     
      }
    }
   
    ?>
   
    </TABLE>
    </BODY>
    </HTML>
    <?php
   
    ob_end_flush();
   
    }
   
 catch(PageError $e) {
   echo $e;
   
 }
 
 ?>

Let’s go over the code above to make it a little bit more clear.
We begin with declaring the show_error() which has the job of clearing the buffer and giving exceptions.
We could have chosen not to use it, but as we are using that function a couple of times it is better to use the function than copying code several times.
Next we have the try block in which our page is generated and the buffer is stared, then we try to connect to the database server and choosing the database we want.

If something goes wrong here the show_error() is called, which means that throwing an exception and a predetermined page with about the error is generated.
The other case is that nothing bad happens and our page is generated as it should and is displayed when we leave the buffer.

This is the elegant approach to this problem, but there is another way in which you can display the same page. The difference lies in the implementation, so instead of creating our own class we can use the Exception class directly.

We then don’t have to declare the class but in my opinion the code is less readable and harder in edit. You can find an example of how this looks below.

<?php

function show_error($message) {

  ob_end_clean();
  throw new Exception($message);
 
  }
 
try { //the same code as in previous example
 
  …..
 
}

catch (Exception $e) {
    echo ‘<html><body>’.$e->getMessage().‘</body></html>’;
    }

?>

You might think that the difference is small but this is because we are dealing with a very easy and uncomplicated example.
In my previous example we could declare our function as abstract and inherit from our PageError class to be able to create a lot of subpages for errors, but in the later example we cannot do that.

Now if we combine the previous buffering technique in part one with the one using exceptions in this one could give even better results.
Also have in mind that you do not have to buffer the entire page at once, but only the dynamic parts or the parts of the page where errors could occur.
How you deal with the problem is up to the individual that is facing them, you’ll just have to find a way you feel comfortable with.

Share with the world: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Slashdot
  • del.icio.us
  • Digg
  • Technorati
  • Reddit
  • StumbleUpon
  • YahooMyWeb
  • DZone
  • MisterWong

Leave a Reply