Added some information about Exceptions.

This commit is contained in:
Phil Sturgeon
2012-07-10 14:40:06 +01:00
parent 75f7a8ec1f
commit 61f3ee4e1d
5 changed files with 83 additions and 19 deletions

View File

@@ -0,0 +1,64 @@
---
isChild: true
---
## Exceptions
Exceptions are a standard part of most popular programming languages, but they are often overlooked by PHP programmers.
Languages like Ruby are extremely Exception heavy, so whenever something goes wrong such as a HTTP request failing, or
a DB query goes wrong, or even if an image asset could not be found, Ruby (or the gems being used) will throw an
exception to the screen meaning you instantly know there is a mistake.
PHP itself is fairly lax with this, and a call to `file_get_contents()` will usually just get you a `FALSE` and a warning.
Many older PHP frameworks like CodeIgniter will just return a false, log a message to their proprietary logs and maybe
let you use a method like `$this->upload->get_error()` to see what went wrong. The problem here is that you have to go
looking for a mistake and check the docs to see what the error method is for this class, instead of having it made extremely
obvious.
Another problem is when classes automatically throw an error to the screen and exit the process. When you do this you
stop another developer from being able to dynamically handle that error. Exceptions should be throw to make a developer aware
of an error, then they can choose how to handle this. E.g:
{% highlight php %}
<?php
$email = new Fuel\Email;
$email->subject('My Subject');
$email->body('How the heck are you?');
$email->to('guy@example.com', 'Some Guy');
try
{
$email->send();
}
catch(Fuel\Email\ValidationFailedException $e)
{
// The validation failed
}
catch(Fuel\Email\SendingFailedException $e)
{
// The driver could not send the email
}
{% endhighlight %}
### SPL Exceptions
An Exception by default has no meaning and the most common to give it meaning is by setting its name:
{% highlight php %}
<?php
class ValidationException extends Exception {}
{% endhighlight %}
This means you can add multiple catch blocks and handle different Exceptions differently. This can lead to
the creation of a <em>lot</em> of custom Exceptions, some of which could have been avoided using the SPL Exceptions
provided in the [SPL extension][splext].
If for example you use the `__call()` Magic Method and an invalid method is requested then instead of throwing a standard
Exception which is vague, or creating a custom Exception just for that, you could just `throw new BadFunctionCallException;`.
* [Read about Exceptions][exceptions]
* [Read about SPL Exceptions][splexe]
[exceptions]: http://php.net/manual/en/language.exceptions.php
[splexe]: http://php.net/manual/en/spl.exceptions.php
[splext]: /#standard_php_library

View File

@@ -11,7 +11,7 @@ CLI PHP programs are powerful because you can use your app's code directly witho
Try running PHP from your command line:
{% highlight bash %}
> php -i
php -i
{% endhighlight %}
The `-i` option will print your PHP configuration just like the [`phpinfo`][phpinfo] function. There are a number of other useful [command line options][cli-options], too.
@@ -19,12 +19,12 @@ The `-i` option will print your PHP configuration just like the [`phpinfo`][phpi
Let's write a simple "Hello, $name" CLI program. To try it out, create a file named `hello.php`, as below.
{% highlight php %}
<?php
if($argc != 2) {
die("Usage: php hello.php [name].\n");
}
$name = $argv[1];
echo "Hello, $name\n";
<?php
if($argc != 2) {
die("Usage: php hello.php [name].\n");
}
$name = $argv[1];
echo "Hello, $name\n";
{% endhighlight %}
PHP sets up two special variables based on the arguments your script is run with. [`$argc`][argc] is an integer variable containing the argument *count* and [`$argv`][argv] is an array variable containing each argument's *value*. The first argument is always the name of your PHP script file, in this case `hello.php`.
@@ -32,10 +32,10 @@ PHP sets up two special variables based on the arguments your script is run with
To run our script, above, from the command line:
{% highlight bash %}
> php hello.php
Usage: php hello.php [name]
> php hello.php world
Hello, world
php hello.php
Usage: php hello.php [name]
php hello.php world
Hello, world
{% endhighlight %}

View File

@@ -7,19 +7,19 @@ More importantly, `PDO` allows you to safely inject foreign input (e.g. IDs) int
Let's assume a PHP script receives a numeric ID as a query parameter. This ID should be used to fetch a user record from a database. This is the `wrong` way to do this:
{% highlight php %}
<?php
$pdo = new PDO('sqlite:users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!
<?php
$pdo = new PDO('sqlite:users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!
{% endhighlight %}
This is terrible code. You are inserting a raw query parameter into a SQL query. This will get you hacked in a heartbeat. Instead, you should sanitize the ID input using PDO bound parameters.
{% highlight php %}
<?php
$pdo = new PDO('sqlite:users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT), PDO::PARAM_INT);
$stmt->execute();
<?php
$pdo = new PDO('sqlite:users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT), PDO::PARAM_INT);
$stmt->execute();
{% endhighlight %}
This is correct code. It uses a bound parameter on a PDO statement. This escapes the foreign input ID before it is introduced to the database preventing potential SQL injection attacks.