I've always been taught that using exceptions in programming allowed for error handling to be abstracted from the objects that throw the errors. Looking at the PHP manual, it seems that PHP has an Exception class and an ErrorException class, indicating that not all exceptions have to be errors. So, I'd like to use them to help with page redirects.
I want to have a hard redirect that will send only a header and no page content. What would be the best way to trigger this? Let's say I have a Controller class with a redirect() method.
Should that method look like this:
class Controller {
public function redirect($path) {
throw new Exception($path, 301);
}
}
...
try {
$controller->redirect('http://domain.tld/redirected');
} catch (Exception $e) {
if ($e->getCode() == 301) {
header('Location: ' . $e->getMessage());
}
}
Or like this:
class Controller {
public function redirect($path) {
header('Location: ' . $path);
throw new Exception('The page is being redirected', 301);
}
}
...
try {
$controller->redirect('http://domain.tld/redirected');
} catch (Exception $e) {
if ($e->getCode() == 301) {
// Output nothing
}
}
Or should I create a new type of exception like this:
class RedirectException extends Exception {
protected $url;
public function __construct($url) {
parent::__construct('The redirects are coming!', 301);
$this->url = (string)$url;
}
public function getURL() {
return $this->url;
}
}
...
class Controller {
public function redirect($path) {
throw new RedirectException($path);
}
}
...
try {
$controller->redirect('http://domain.tld/redirected');
} catch (RedirectException $e) {
header('Location: ' . $e->getURL());
}
While I feel like all of these would work, none of them feel right to me. The last seems the closest since it makes it clear that the URL is a required member. However, an exception like that would serve only one purpose. Would it make more sense to build a RequestException that handles all 3XX, 4XX, and 5XX status codes? Plus, what about the message? Does that just become extraneous information at this point?
headers_sent(). Your exception handlers can potentially kick in at any stage of a page's creation, and the redirect would only work if the exception occurs BEFORE any output. Otherwise you'll just get the "headers already sent" warnings and no redirect will occur. A somewhat safer usage would be:if (headers_sent()) { ... output a <meta> redirect + javascript document.location block ... } else { header('Location: ...'); }