Based on the number of questions I see on sites like stackoverflow around PHP errors and things I've seen during code reviews, it seems the different error settings in PHP are a bit of a mystery to many PHP developers. In my opinion having a good understanding of the different settings around error messages is vital. If you don't know how to set the error reporting level, how errors are logged or how and when to show errors on the screen it makes debugging much more difficult.
Some of the most important settings around errors include:
The error_reporting setting defines what kinds of messages are reported. See http://www.php.net/manual/en/errorfunc.constants.php for the different error levels. It is possible to disable error messages completely by setting error_reporting to 0, but I can't think of a good reason to do this. Ever.
I recommend always setting the error level to E_ALL in production, and E_ALL | E_STRICT in dev and test. This will ensure that you're aware of all types of errors, and even notified of improvements that could be made to your code.
Display errors determines if errors are printed to the screen. Because error messages can give detailed information about your site, server setup, operating system, and more, display errors should always be turned off in production.
I recommend always enabling display_errors in dev and test. Having the error messages stare you in the face when you're working on dev and test can make it much easier to identify and resolve issues. Along with this, I recommend installing Xdebug in dev and test. Xdebug provides great formatting of error messages as well as stack traces so it's easier to identify exactly where an error occurred.
This setting enables error logging. It should always be enabled, especially in production. Reviewing error logs on a regular basis is a great way to identify code issues that you may not be aware of, as well as troubleshooting known issues.
This setting is used to specify where to log PHP errors. By default when using PHP with Apache, PHP errors will be sent to the apache error log. Separating the two log files can be useful, but is not required. The benefit of separating the two is that you don't have to wade through 404s or other Apache level errors that may not be related to your code. If you do separate the two, I suggest reviewing each of them regularly as the Apache logs can also be quite helpful in identifying issues with your site.
If you enable this setting the last error message will be stored in the $php_errormsg variable. This is probably one of the lesser used error settings, but it can be very useful in certain situations.
PHP also supports an error suppression operator, the @ sign. When used, any errors that result from the following expression will not be reported. Read that again. I didn't say it fixes errors, or eliminates errors, or makes your code work any differently. I said PHP won't tell you that an error occurred. The error suppression operator should only be used in very rare, and very specific cases.
If you decide to use the error suppression operator, you'll need to be extra careful about checking for error conditions around that code. Even though the error won't be logged or displayed to the screen, the error message will be available in $php_errormsg if you enable the track_errors setting. Using this setting along with the error suppression error can improve your code, but it should not be an excuse to use the error suppression operator.
Anytime you use the error suppression operator, add a comment explaining why you're using it. If you have to explain to everyone who reads your code in the future why you did something, you're more likely to explore better options first. For those cases where it really is the right way to solve a problem (despite my warnings against using it, there's occasionally a very good reason to use it) having that documentation will save future developers the effort of figuring out why it's being used.
CodeIgniter 2.0 was released a few days ago, and one of the (much overdue) features I'm looking forward to using is the ability to define a custom 404 controller. This is useful for handling requests to non-existant controller methods by specifying a controller to call instead. Here's how to get it setup:
$route['404_override'] = 'error/error_404';
You should now have a functional error controller for 404s when triggered by a request for non-existent controller methods. But what if you want to trigger 404s from your code and use the error controller?
Something like this, perhaps?
// Get an article from the database, show a 404 page if the requested article was not found.$article = get_content($this->uri->uri_string();
if(empty($article){
show_404($this->uri->uri_string());
}Unfortunately, this will still use the built-in non-controller error message. I got to playing around and discovered that (at least in CI 2.0, maybe 1.7.2) you can do this:
$article = get_content($this->uri->uri_string();
if(empty($article){
include(APPPATH.'controllers/error.php');
$error = new Error();
$error->error_404();
}Of course you could do the same thing for other error types (403, 500, etc) by creating new methods in the Error controller and calling the correct method. It could even be simplified more by creating a helper with a function such as this one:
function custom_error($status_code = 404){
$method_name = 'error_'.$status_code;
include(APPPATH.'controllers/error.php');
$error = new Error();
$error->$status_code();
}I just saw this article in my RSS feeds, and was amazed at the complexity of the solution to a simple problem. The goal was to change query strings in a URL to the new values passed in as an associative array. If the URL didn't have a query string, add one using the array. Also, query strings in the original URL not in the array shouldn't be modified.
The provided function uses regular expression matching, multiple foreach loops, and really makes the problem more complex than it needs to be.
<?php$url = modify_url(array('p' => 4, 'show' => 'column'), 'http://www.example.com/page.php?p=5&show=list&style=2');
$url is now http://www.example.com/page.php?p=4&show=column&style=2
So here's my version:
<?phpfunction modify_url($mod, $url = FALSE){
// If $url wasn't passed in, use the current urlif($url == FALSE){
$scheme = $_SERVER['SERVER_PORT'] == 80 ? 'http' : 'https';
$url = $scheme.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
} // Parse the url into pieces$url_array = parse_url($url);
// The original URL had a query string, modify it.if(!empty($url_array['query'])){
parse_str($url_array['query'], $query_array);
foreach ($mod as $key => $value) {
if(!empty($query_array[$key])){
$query_array[$key] = $value;
} } } // The original URL didn't have a query string, add it.else{
$query_array = $mod;
}return $url_array['scheme'].'://'.$url_array['host'].'/'.$url_array['path'].'?'.http_build_query($query_array);
}I'm guessing the original author is just not familiar with parse_str, parse_url and http_build_query.
Moral of the story: regularly read through the PHP manual to see what's available. You'll save yourself time in the long run, and avoid re-inventing the wheel so often.
(Yes, I'm fully aware that I've just become that guy in XKCD.)

This post was originally written several years ago and included my own attempt at building a very simple ical creator in PHP. I've been meaning to update this blog with some better code and information for quite some time. I finally found what I consider to be a very good class for creating iCalendar files using PHP: iCalcreator. Along with creating iCalendar files, iCalcreator can also parse and merge iCalendar files, and spit out a modified version. There are lots of examples available for download on their site, as well as supporting utilities.
The iCalcreator documentation is excellent. The examples are easy to follow, and they clearly document how to use their class. Unfortunately, the iCalendar specification is complicated enough that you'll still need to read rfc2445 to really take advantage of all of the options available to you. Some good iCalendar reference sites include:
Since I haven't actually built anything using iCalcreator yet (other than some quick test scripts earlier today) I can't really answer any questions about its usage. The good news is they have a forum on sourceforge for questions. I'd love to hear about your experiences using iCalcreator, so feel free to leave your comments below.
One benefit to working as part of a development team is that you can ask your fellow developers to look at your code and ask for help. Sending code back and forth over email can be frustrating and even counter-productive. IMO, the ideal way to share code is by simply sending a URL and letting the other developer view it in their browser with syntax highlighting.
Here's one way that does not require any external libraries and is very easy to setup:
RewriteRule ^(.*)\.phps$ viewsource.php?file=$1.php [QSA,L]<?php// This script should *NEVER* be used on a production server!// By default, it will only run on localhost. If you want to run this script on// a staging server add the IP address of that server to $allowed_servers.$allowed_servers = array('127.0.0.1');
// Set $base_dir to the root of your web directory.$base_dir = $_SERVER['DOCUMENT_ROOT'];
// Make sure this script is running on an allowed server.if(!in_array($_SERVER['SERVER_ADDR'], $allowed_servers)){
die('Do not run this script in production!');
}// Exit if no file was specifiedif(empty($_GET['file'])){
die('No file specified.');
}// Ensure the requested file is inside $base_dir and that it exists$real_path = realpath($base_dir.$_GET['file']);
if(strpos($real_path, $base_dir) === false || $real_path === false){
die('Access denied or file not found.');
}?><html>
<head>
<title><?= $real_path ?></title>
<style type="text/css">
.num_margin {text-align: right;
margin-right: 6pt;
padding-right: 6pt;
border-right: 1px solid gray;
}
.num_margin a {color: gray;
font-size: 13px;
font-family: monospace;
}
body { margin: 0px; margin-left: 5px; } div { float: left; }</style>
</head>
<body>
<?php$lines = '';
$lines_array = range(1, count(file($real_path)));
foreach($lines_array as $line){
$lines .="<a href=\"#$line\" name=\"$line\">$line</a><br />";
}$content = highlight_file($real_path, true);
echo "<div><div class=\"num_margin\">$lines</div><div>$content</div></div>";
?></body>
</html>
Now when you visit a link like: http://localhost/info.phps it will show the source of the file.
Note: This script should never be used in production!