Autor Zpráva
RastyAmateur
Profil
Dobrý den,

rád bych si vytvořil vlastní třídu na výjimky. Je to proto, protože try&catch mi nyní velice pomohlo a nemám tedy v plánu to předělávat. Zachytím v určitém bloku danou chybu a tu bych rád vypsal uživateli. Jenže potřebuji rozeznávat chyby, které jsou způsobené vstupem či uživatelem (které uživateli vypsat) a chyby, které se staly na straně serveru či databáze (omluvit se a upozornit administrátora). Představuji si tedy vytvořit třídu, ve které kromě zprávy bude také nějaká hodnota (bool) $public.

extends Exception: něco v následujícím duchu
<?php
class MyException extends Exception
{
  private $public;
  
  public function __construct($message, $public = true)
  {
    $this->public = (bool) $public;
    parent::__construct($message);
  }
  
  public function isPublic()
  {
    return $this->public;
  }
}

dále jsem někde četl něco o implements Throwable, ale článek nemohu zpětně dohledat. Co jsem tak našel mezi tím, mělo by jít o třídu typu class MyException implements Throwable. Pokud jsem to dobře pochopil, daná třída (nebo její rodič?) musí být z interface Throwable aby se mohlo použít throw new MyException();

Existuje tedy vůbec to druhé řešení (s implements Throwable)? Jelikož jsem nikde moc neviděl toto řešení, tak předpokládám, že první řešení (s extends Exception) by mělo být lepší, je tomu tak? Nebo existuje ještě nějaké řešení, které jsem vůbec nenašel a ani mě nenapadlo?

Děkuji :-)

Když jsem sepsal dotaz, všiml jsem si, že u třídy Exception je ještě jakási proměnná protected $code. Má ta zde nějaký smysl, nebo by teoreticky mohla sloužit mým účelům? Bylo by pak možné trošku poupravit danou třídu, aby mi to při vytváření instance poslalo email o chybě?
CZechBoY
Profil
cz.php.net/throwable je potřeba dědit třídu Exception (viz poznámka).
Kód chyby je interní záležitost a uživatelovi by to asi k ničemu nebylo.
Jakub J.
Profil
Reaguji na RastyAmateura:
Throwable
Viz dokumentace: „PHP classes cannot implement the Throwable interface directly, and must instead extend Exception.
Abys rozlišil původ/účel výjimky, můžeš si vytvořit rozdílné rodiče:

class UserCausedException extends Exception {}
class SanityException extends UserCausedException {}

class SystemCausedException extends Exception {}
class DataIntegrityException extends SystemCausedException {}

try {
    // …
catch(Exception $e){
    if($e instanceof UserCausedException){
        // vynadej uživateli, že něco pokazil
    } elseif($e instanceof SystemCausedException){
        // odešli zprávu administrátorovi a omluv se uživateli
    } else {
        // výjimku pravděpodobně vyhodil kód třetí strany
    }
}
Keeehi
Profil
RastyAmateur:
Hlavní problém toho celého je že by jsi neměl výjimky znásilňovat nějakým posíláním emailů.

Měl by sis vytvořit 2 (reálně asi mnohem více) výjimek a ty používat
class UserInputException extends Exception {}
class ServerException extends Exception {}

O odeslání emailu by se měla starat jiná část aplikace.
try {
    // kód který může způsobit  výjimku
} catch (UserInputException $e) {
    echo "Zadal jste neplatný vstup";
} catch (ServerException $e) {
    mail();
}

Případně si na obsluhu výjimek můžeš vytvořit nějaký aparát, aby jsi to odesílání neměl přímo v kódu, ale dělo se vedle.
class ExceptionManager {
    protected $toSend=[ServerException::class];
    
    public function catched(Exception $exception) {
        if(in_array(get_class($exception), $this->toSend)) {
            mail();
        }
    }
}

$exceptionManager = new ExceptionManager();

try {
    // kód který může způsobit  výjimku
} catch (UserInputException $e) {
    echo "Zadal jste neplatný vstup";
    $exceptionManager->catched($e);
} catch (ServerException $e) {
    $exceptionManager->catched($e);
}

Třída ExceptionManager zase nemusí mít konfiguraci natvrdo v sobě, ale může si jí od někud načítat, nebo lépe jí může být předána při inicializaci. Těch možností je spoustu.
RastyAmateur
Profil
Keeehi:
Hlavní problém toho celého je že by jsi neměl výjimky znásilňovat nějakým posíláním emailů.
Proč ne? Teoreticky to spolu souvisí...
Hando
Profil
Tak jde o to, udržet tu logiku přehlednou, čistou a ideálně dle myšlenky DRY. Navíc odesílání e-mailů bude zbytečně prodlužovat zpracování (i když, když už to vyvolá výjimku...) a není 100% jisté, že se to povede.
Navíc pokud se rozhodneš, že budeš výjimky zpracovávat jinak, tak přeci nebudeš vše přepisovat.
Toť můj názor, třeba mě někdo opraví/doplní.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: