Pro výjimky platí to co všude.
a) Pokud víte, jak výjimku ošetřit, a dostat se do rozumného stavu - použijte try/catch, a výjimku chyťte a ošetřete.
b) Pokud nevíte, jak výjimku ošetřit, ale je třeba změnit typ/zprávu výjimky na něco jiného, pro volající vrstvy vhodnějšího - použijte try/catch, výjimku chytněte a vyhoďte namísto ní vhodnější výjimku.
c) Pokud nevíte co s výjimkou, nechte jí proplavat výše.
V mojom prípade by to malo byť a. Ale mne sa jednoducho nepáči kód "zasvinený" try/catch blokmi. Preto by som rád to nechal plávať vyššie. Neviem či sa dajú priamočiaro preniesť best practices z Javy to PHP; Java zásadne vždy robí všetko komplexne a zložito. Rád by som našiel aj k výnimkám niečo ako the PHP way, ale nepodarilo sa. Pozdával sa mi názor z PHP delusions, ktorý som uviedol, avšak to je názor len z jedného zdroja a tak som opatrný.
PHP si samo se sebou neví moc rady. Doporučuji prostě přenést obecné best practices, jen tak dáte PHP štábní kulturu.
Java některé věci dělá dobře, jinými věcmi zase spíše kompenzuje to, že jazyk nic neumí, je příliš jednoduchý. Ale ve výjimkách to dělá spíše dobře.
Osobně se nevyhýbám kódu plnému try/catch, když to má smysl. Myslím, že nejlepší co se dá udělat je vyřešit chybu/výjimku co nejblíže místu, kde vznikla. Tedy, pokud umím na nějakém místě ošetřit chybu/výjimku, tak to udělám.
1) Pokud mohu šíření výjimky zcela zastavit a převést program do stabilního stavu, je to moje první snaha.
2) Pokud chytám výjimku, jejíž typ a popis je příliš low level, a směrem nahoru se nehodí, tak výjimku zachytím a vyhodím vhodnější. Například pro funkci getCachedImage() se příliš nehodí vyhodit výjimku FileNotFoundError(), ale je lépe ji změnit na CachedImageNotFoundError(). Funkce výše nemusejí vědět, jak je kešovaný obrázek uložen, je zajímá, že ho nelze získat.
Cílem je posílat nahoru co nejméně chyb a výjimek. Pokud je možné něco vyřešit na místě, nechť je to vyřešeno. Ošetřování chyb je vždy "nehezké", nehledím proto na počet try/catch, či počet if/elseif či dalšího. Nejlepší možný stav je mít kód, který generuje co nejméně chyb směrem nahoru, a posílá chyby/výjimky jen tehdy, když to nejde řešit jinak.
Dalším cílem je posílat nahoru (volajícím) chyby, kterým "hořejšek" (volající) rozumí. Viz ad 2).
Každý framework/program by měl mít na úrovni funkce main() zachytávač všech nezpracovaných výjimek, které převede do nějakého rozumného hlášení uživateli a případně zaloguje. To je ale věc frameworku, to by uživatel řešit neměl.
***
Co by se nikdy dít nemělo, je zachycovat všechny výjimky bez ošetření. Toto je prasárna hrubého zrna, za kterou by měl jít programátor klečet na hrách:
try { ... } catch (Throwable/Exception $e) {} # PHP 7 = Throwable, PHP 5 = Exception
***
Nejtěžší je u projektu vymyslet vlastní strom tříd výjimek, aby byl logický a dobře, přitom jednoduše, vyjadřoval možné chyby v kódu.