I wanted some system where I didn’t have to keep looking at the Exception class and copying either status codes or text all at once. I also didn’t want to have to keep writing plain English error messages after catching exceptions. This seems to accomplish both, plus allows for easy IDE auto-completion!
Here’s some demo code:
<?php
class Thrive_URL_Exception extends Thrive_PrettyException
{
const MISSING_CURL = "The cURL PHP extension must be enabled.";
const MISSING_URL = "A URL has not been supplied or set.";
const INVALID_URL = "The URL '%s' is not valid.";
const BLANK_URL = "The URL '%s' contained no data. It is probably invalid.";
const CONNECTION_TIMED_OUT = "The connection timed out.";
const FILE_NOT_FOUND = "404: '%s' could not be found.";
const NOT_ACCESSIBLE = "%d: '%s' is not currently accessible.";
const PERMISSION_DENIED = "Permission denied.";
}
class Thrive_URL_Downloader
{
public function fetch($url)
{
// Make sure the URL is valid.
if (!self::isURLValid($url))
{
throw new Thrive_URL_Exception(Thrive_URL_Exception::INVALID_URL, array($url));
}
$ch = curl_init();
curl_setopt_array($ch, array(CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADERFUNCTION => array($this, 'captureHeader'),
CURLOPT_TIMEOUT => 30,
)
);
$data = curl_exec($ch);
curl_close($ch);
if ($data === false || is_null($data) || $data == '')
{
throw new Thrive_URL_Exception(Thrive_URL_Exception::BLANK_URL, array($url));
}
// TODO: Need to handle HTTP error messages, such as 404 and 502.
$info = $this->getUrlInfo($ch);
if ($info->httpCode == 401)
{
throw new Thrive_URL_Exception(Thrive_URL_Exception::PERMISSION_DENIED);
}
if ($info->httpCode == 404)
{
throw new Thrive_URL_Exception(Thrive_URL_Exception::FILE_NOT_FOUND, array($url));
}
if (in_array($info->httpCode, array(400, 401, 402, 403, 500, 501, 502, 503)))
{
throw new Thrive_URL_Exception(Thrive_URL_Exception::NOT_ACCESSIBLE, array($info->httpCode, $url));
}
$urlContent = new Thrive_Model_URLContent;
$urlContent->url = $url;
$urlContent->headers = $this->headers;
$urlContent->info = $info;
$urlContent->content = $data;
return $urlContent;
}
}
My question is whether there’s an obviously better way to do this sort of thing??
IMHO it’s not best solution.
Your exception class is breaking Single Responsibility Principle (SRP)Wikipedia, because you are using same exception class for different kind of errors. What I’ll do is:
Create single exception class for different kind of error:
Then you can use excetion without passing any messages. The message is private part of class.
For larger application this solution is better IMHO.