This is our PHP redirect() function, it has been tested with PHP versions >= 4.2.0. Seen a lot of requests for this on various mailing lists so we thought we'd share.
We've added support for different HTTP/1.1 3XX status codes. Each of the response codes tell the requesting User-Agent how to respond as described below.
In the W3C specification it's stated that the server should also give some content back for the User-Agent to render if it does not obey the redirect. This redirect function will output some pretty HTML if the headers have already been sent following the W3C intentions.
- 301 Moved Permanently - Forget the old page existed
- 302 Found - Use the same method (GET/POST) to request the specified page.
- 303 See Other - Use GET to request the specified page. Use this to redirct after a POST.
- 307 Temporary Redirect - Good for response to POST.
Usage example
<?php
// Do stuff here before sending headers
redirect('/')
redirect("/my/page")
redirect("http://www.foo.bar/page.htm",303)
redirect("./index.php",307)
?>
The redirect function itself
You may copy and paste this code freely where you need to, please give us credit it if you use it
public static function redirect($uri,$code=302)
{
// Specific URL
$location = null;
if (substr($uri,0,4)=='http') {
$location = $uri;
} else {
$location = self::base(true);
// Special Trick, // starts at webserver root / starts at app root
if (substr($uri,0,2) == '//') {
$location .= '/' . ltrim($uri,'/');
} elseif (substr($uri,0,1) == '/') {
$location .= '/' . ltrim($uri,'/');
}
}
// $sn = \$_SERVER['SCRIPT_NAME'];
// $cp = dirname($sn);
// $schema = \$_SERVER['SERVER_PORT']=='443'?'https':'http';
// $host = strlen(\$_SERVER['HTTP_HOST'])?\$_SERVER['HTTP_HOST']:\$_SERVER['SERVER_NAME'];
// if (substr($to,0,1)=='/') $location = "$schema://$host$to";
// elseif (substr($to,0,1)=='.') // Relative Path
// {
// $location = "$schema://$host/";
// $pu = parse_url($to);
// $cd = dirname(\$_SERVER['SCRIPT_FILENAME']).'/';
// $np = realpath($cd.\$pu['path']);
// $np = str_replace(\$_SERVER['DOCUMENT_ROOT'],'',$np);
// $location.= $np;
// if ((isset(\$pu['query'])) && (strlen(\$pu['query'])>0)) $location.= '?'.\$pu['query'];
// }
// }
$hs = headers_sent();
if ($hs === false) {
switch ($code) {
case 301:
// Convert to GET
header("301 Moved Permanently HTTP/1.1",true,$code);
break;
case 302:
// Conform re-POST
header("302 Found HTTP/1.1",true,$code);
break;
case 303:
// dont cache, always use GET
header("303 See Other HTTP/1.1",true,$code);
break;
case 304:
// use cache
header("304 Not Modified HTTP/1.1",true,$code);
break;
case 305:
header("305 Use Proxy HTTP/1.1",true,$code);
break;
case 306:
header("306 Not Used HTTP/1.1",true,$code);
break;
case 307:
header("307 Temporary Redirect HTTP/1.1",true,$code);
break;
}
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header("Location: $location");
}
// Show the HTML?
if (($hs==true) || ($code==302) || ($code==303)) {
// todo: draw some javascript to redirect
$cover_div_style = 'background-color: #ccc; height: 100%; left: 0px; position: absolute; top: 0px; width: 100%;';
echo "<div style='$cover_div_style'>\n";
$link_div_style = 'background-color: #fff; border: 2px solid #f00; left: 0px; margin: 5px; padding: 3px; ';
$link_div_style.= 'position: absolute; text-align: center; top: 0px; width: 95%; z-index: 99;';
echo "<div style='$link_div_style'>\n";
echo "<p>Please See: <a href='$uri'>".htmlspecialchars($location)."</a></p>\n";
echo "</div>\n</div>\n";
}
exit(0);
}
See Also
- RFC 2616 - the spec.
- Redirect in response to POST
- RFC 1945 for HTTP/1.0
- RFC 2068 for HTTP/1.1.
Notes & Comments
thank you boss/vova on 26 Jan 2010
Excellent work. Very helpful./ratfactor on 26 Feb 2010


Visitor Maps