Załóżmy, że mamy klasę File. Klasa ta posiada konstruktor, nadający obiektowi nazwę zgodną z nazwą pliku. Konstruktor wywołuje także prywatną metodę, sprawdzającą czy plik da się obsłużyć:
public function __construct($str)
{
$this->filename = $str;
$this->readable();
}
private function readable()
{
if (!$this->ptr = @fopen($this->filename, 'r')) {
throw new Exception("Cannot read " . $this->filename . " file");
}
}
I w kontrolerze mamy osadzony kod:
try {
$fileobj = new File("filename.txt");
} catch (Exception $e) {
$error = $e->getMessage();
...
}
Gdy nie ma pliku w podanej lokalizacji lub prawa dostępu nie pozwalają na jego otwarcie, to w obu przypadkach dochodzi do zrzucenia wyjątku. Załóżmy, że chciałbym obsłużyć obie te sytuacje niezależnie. Jak to zrobić?
Sposób 1:
if (plik nie istnieje) {
throw new Exception("Brak pliku");
} else if (nie udalo sie otworzyc pliku) {
throw new Exception("Plik odmawia dostepu")
}
Sposób 2:
if (plik nie istnieje) {
throw new NoFileException("Brak pliku");
} else if (nie udalo sie otworzyc pliku) {
throw new NoAccessException("Plik odmawia dostepu")
}
class NoFileException extends Exception
{
...
}
class NoAccessException extends Exception
{
...
}
Wiem, że można tworzyć klasy swoich wyjątków, nie wiem jednak co miałoby w nich być umieszczone, wszak wszystko da radę obsłużyć, drukując odpowiedni komunikat wyjątku. Jaka jest więc korzyść w definiowania własnych wyjątków?
Sposób 3:
Ten sposób opisywał Comandeer. Tylko że opis na stronie PHP jest dla mnie zbyt lakoniczny i nie mogę dopasować żadnego z predefiniowanych wyjątków do swoich potrzeb.
Pytanie jest więc jak to zrobić poprawnie? Nie rozumiem też dlaczego zrzuca się kod błędu. Używając kodu, który jest na samej górze wiadomości, zawsze otrzymuję wartość 0, niezależnie czy pliku nie ma w podanej lokalizacji, czy skrypt nie ma uprawnień do jego otwarcia. Wiem, że kod błędu podaje się jako drugi parametr, ja nie podałem, stąd 0. Ale czy nie powinno być tak, że wyjątek zrzuca wbudowany kod błędu? Skoro skrypt został przerwany, to pewnie wie z jakiego powodu. Zresztą jeśliby usunąć @ przy fopen() to są drukowane pewne informacje.