• Aucun résultat trouvé

The first rule of professional, modern PHP error handling is that die(error()) is dead. It has no benefits to offer and works against a positive user experience as well as undermining security by revealing system details to untrusted sources. PHP has two error reporting systems in place, Errors and Exceptions. Each produces its own messages, and both need to be captured, privately logged, and never revealed as raw data to the user.

Good error management consists of at least three actions.

1. Capture error information

2. Log error and file details to a private log 3. Implement custom directions for users

In order to capture error information, errors need to be checked for. Simple as that sounds, this process is often overlooked when data returned from one function is immediately passed into another function via function chaining, or function stuffing, as in die(error()) or echo json_encode(pdo->fetchall()). The extra step has to be taken to check results.

Logging information requires setting up an error file outside of the public web root and making the handle available for writing during script execution.

Implementing custom error directions for users is the most difficult by far. This involves planning in two areas, anticipating some of the errors that could occur, and preparing quality responses that do not annoy users. However, this is one of the most important steps in terms of creating a good experience for users. To this end, this sec-tion covers what is usually the last step first because this is what the user sees.

A few conditions that could be expected are:

• Database unavailable

• Data not available

• User input invalid

• File not found

• Image not found

Part of PHP error management involves working with the web server to prepare custom responses to replace default behavior. For Apache, this involves using the

ErrorDocument directives in .httpaccess to map error codes to custom response pages.

This is done by adding the following lines to .httpaccess:

ErrorDocument 400 /badRequest.php ErrorDocument 401 /badAuth.php ErrorDocument 403 /forbidden.php ErrorDocument 404 /pageNotFound.php

ErrorDocument 500 /internalServerError.php

Default behavior always negatively affects quality, so implementing good messages for users enhances the quality of a site. A few design considerations that should go into custom messages are:

• Use an error page design consistent with the look and feel of the site.

• Provide a message targeted for response needed; technical errors are meaning-less to users.

• Be polite.

• Be helpful to the users, not to the developers.

• Give the user useful options. Keep in mind what the user can do, not what a developer should do.

• Always remember that users can get annoyed and leave.

Configuring PHP Error Environment Secure php.ini and Error Log Files

To ensure an ongoing secure environment, it is important that configuration and log files not be tampered with. There are two basic steps for protecting configuration files.

• First, set file permissions on php.ini to 600.

• Second, these settings can be added to the root .httpaccess so that Apache will protect the PHP environment files.

Add this section to .httpaccess to protect php.ini:

# deny access to php.ini

<Files php.ini>

order allow,deny deny from all satisfy all

</Files>

Next, add this section to .httpaccess to protect the error log itself:

# deny access to php error log

<Files error.log>

order allow,deny

deny from all satisfy all

</Files>

Error Options Overview

Here is a brief explanation for each of the error configuration options for PHP.

Disable displaying startup errors. In production, users should not see system errors.

display_startup_errors = false

Disable displaying all errors. In production, users should not see system errors.

display_errors = false Enable error logging to a file.

log_errors = true Path to php error log.

error_log =/private/error.log

Disable ignoring of repeat errors. Set to true to only capture first case.

ignore_repeated_errors = false

Disable ignoring of unique source errors. Set to true to only capture first case.

ignore_repeated_source = false Disable HTML markup for errors.

html_errors = false

Enable logging of php memory leaks.

report_memleaks = true

Preserve most recent error via php_errormsg. track_errors = true

Record all php errors.

error_reporting = 999999999 Disable max error string length.

log_errors_max_len = 0

Production Error Configuration for php.ini

This is a recommended base configuration for a production environment. Important points are that it turns displaying raw system messages to users, and sets logging to a private file. The path and file name are configurable. This configuration sets ignoring repeating errors to true. This means the first error will be captured but not subsequent errors of the same type, which makes logs more manageable to review. However, there are cases when knowing how many errors occur and how often they occur is important.

For those cases, set to false in order to get a true sense of the actual problem in production.

ERROR OPTIONS SETTING

display_startup_errors false display_errors false

log_errors true

error_log /private/error.log

ignore_repeated_errors True—set to false if tracking repeated errors is important ignore_repeated_source True—set to false if tracking repeated errors is important html_errors false

error_reporting 999999999 log_errors_max_len 0 report_memleaks true track_errors true

Development Error Configuration for php.ini

This configuration is a starting point for development. It is configured to show all errors as output and to log all errors to a file. It captures all repeating errors to help alert problem areas.

ERROR OPTIONS SETTING

display_startup_errors false display_errors false

log_errors true

error_log /private/error.log ignore_repeated_errors false

ignore_repeated_source false

html_errors false

error_reporting 999999999 log_errors_max_len 0 report_memleaks true track_errors true

PHP Error Level Constants

This table comprises the error codes that PHP will report, which can be tested for in code to make determinations about how to continue. Error constants can be combined using the OR operator |.

VALUE CONSTANT DESCRIPTION 1 E_ERROR Fatal run-time error. Execution of the script is halted 2 E_WARNING Non-fatal run-time error. Execution of the script is not halted 4 E_PARSE Compile-time parse error

8 E_NOTICE Run-time notice. Indicates the script found something that might be an error, but could also happen when running a script normally

16 E_CORE_ERROR Fatal errors that occur during PHP’s initial startup

32 E_CORE_WARNING Non-fatal run-time errors. This occurs during PHP’s initial startup 256 E_USER_ERROR User-generated error message. This is like an E_ERROR, except it is

generated in PHP code by using the PHP function trigger_error()

512 E_USER_WARNING User-generated warning message. This is like an E_WARNING, except it is generated in PHP code by using the PHP function

trigger_error()

1024 E_USER_NOTICE User-generated notice message. This is like an E_NOTICE, except it is generated in PHP code by using the PHP function

trigger_error()

2048 E_STRICT Enable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code

4096 E_RECOVERABLE_ERROR Catchable fatal error. E_ERROR can be caught by a user defined handle

8191 E_ALL All errors and warnings, except level E_STRICT

Exception Handling

Exception handling is the object-oriented method for handling errors. An exception is an object, and is instantiated in the same way as an object. The benefit of having an error as an object is the encapsulation of an error state that an object can provide.

The key words for exception handling are try, throw, and catch. The advantages are that code can be protected with a try statement, and an error response implementation is guaranteed to be executed with a catch statement if something goes wrong anywhere in the try statement. The benefit of the throw keyword is that it allows code some-where else up the call stack to catch the thrown exception and respond. Essentially, this puts the compiler to work for you in setting up a guaranteed error path and response system.

Introduction to Exceptions

In PHP an exception is an object of the Exception class. An exception is created and thrown like this.

throw new Exception();

The exception class has a list of member functions used for encapsulating error state, allowing error objects to be used in very effective ways, both for logging and

passing information up the call stack to a handler. Here is a list of the Exception class’

members.

• getCode(). The exception code.

• getMessage(). The exception message.

• getFile(). The file name from where the exception was thrown.

• getLine(). The line number where the exception was thrown.

• getTrace(). An array of call stack information.

• getTraceAsString(). Call stack information as a string.

• getPrevious(). Exception thrown before the current one, if present.

• _ _toString(). Entire exception as a string.

An example of using exceptions is in validating data for other objects. In this case, an AccountMember object requires names to be strings fewer than 40 characters in length, and not integers. When parameters passed to the AccountManager constructor do not meet this requirement, an exception is thrown with a contextual message.

class AccountMember {

private $_userName;

public function _construct($name)

{ $this->_name = self::validateName($name); } private static function validateName($name) {

if(is_string($name) && mb_strlen() < 40) return $name;

throw new Exception("Invalid name properties").

}

Public function getName() { return $this->_name;}

}

$member = new AccountMember("Mike");

echo $member.getName();

will correctly output “Mike”.

If this class is instantiated with the wrong data type,

$member = new AccountMember(5);

an exception is thrown. However, because there was no catch handler implemented, the exception is uncaught, so PHP catches it, and its default behavior is to do a call stack dump in addition to dumping the custom message we passed to the exception we created. Exceptions, once thrown, keep traveling up the call stack until some-one catches them. If no one does, PHP handles it with the default exception handler.