__toString a vyjímky - smrtelná kombinace

V současnosti implementuju komunikaci s ARESem (přístup do registru ekonomických subjektů) a chtěl jsem si trochu ulehčit psaní. Mám objekt dotazu, který na základě nastavených parametrů sestaví buď URL s parametry pro případ dotazu pomocí GET nebo XML dokument pro případ POST dotazu. Jelikož dotaz sám ví, jestli bude pomocí GET nebo POST, rozhodl jsem se generování dotazu implementovat jako magickou metodu __toString(). A zle jsem narazil.

Abych byl přesný - celkem pro generování mám tři metody:

  • toUrl() - pro požadavky GET
  • toXml() - pro požadavky POST
  • __toString() - rozhoduje se podle nastavení objektu

__toString() funguje čistě jako proxy metoda, která na základě nastavení objektu zavolá toUrl() nebo toXml() a vratí její výsledek. Jenomže problém! Metody toUrl() a toXml() používají pro hlášení chyb vyjímky. Ale jakmile se zavolá metoda __toString() a dojde k chybě a vyjímka probublá do __toString(), php vyhodí fatal error:

Fatal error: Method Ss_Ares_Dotaz::__toString() must not throw an exception in /home/sniper/php-projekty/arestest.php on line 30

Cili __toString() nesmí vyhazovat vyjímky. Důvod tohoto opatření mi není zcela jasný a podle mne by ho v dohledné době měli autoři PHP změnit. Ale v součanosti to tak platí a musíme se s tím nějak vypořádat. A řešení je relativně jednoduché - vyjímku vyhodit nemůžeme, ale můžeme vyhodit běžnou chybu. Tedy místo jednoduchého:

public function __toString()
{
    switch ($this->_method) {
        case self::METHOD_GET:
            return $this->toUrl();
        break;
        case self::METHOD_POST:
            return $this->toXml();
        break;
    }
}

je nutno použít takovou trochu kostrbatější konstrukci, na kterou se přeci jenom trochu hůře reaguje než na vyjímku:

public function __toString()
{
    try {
        switch ($this->_method) {
            case self::METHOD_GET:
                return $this->toUrl();
            break;
            case self::METHOD_POST:
                return $this->toXml();
            break;
        }
    } catch (Exception $e) {
        trigger_error($e->getMessage(), E_USER_ERROR);
    }
}	

Vloženo dne 05. 10. 2009       Přidat do záložek na jagg.czPřidat do záložek na linkuj.cz

Diskuse

Snad žádný javař zvyklý na řízené výjimky se tomu nediví :-D Toto opatření prostě umožňuje použít __toString() s jistotou, že se to povede. OT: Ta hláška o nedefinovaném indexu HTTPS (dole) nevypadá dobře.

Vložil v6ak

ad OT: Hops, dik za upozorneni....budiz mi omluvou ze nepochazela z mojeho kodu ale z includu backlinks :)

Vložil Sniper