Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Exception handling z przywracaniem, Problem użycia restore wewnątrz handler'a (PHP 7.3.4)
session
post
Post #1





Grupa: Zarejestrowani
Postów: 112
Pomógł: 22
Dołączył: 11.04.2010
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Witajcie!

Przejdę od razu do rzeczy:
  1. function catchable($e) {
  2. if(get_class($e) === 'PDOException')
  3. echo 'Database problem';
  4.  
  5. restore_exception_handler();
  6. throw $e;
  7. }
  8.  
  9. function unknown($e) {
  10. echo 'Something went wrong';
  11. }
  12.  
  13. set_exception_handler('unknown');
  14. set_exception_handler('catchable');
  15.  
  16. throw new Exception('Catch me!');


Kod zwraca Uncaught Exception.

Jest to dla mnie nieoczekiwane zachowanie z kilku powodów:
1. Nie ma przeciwwskazań do wywoływania innych funkcji (również user-defined) z samego callback'a
2. set_exception_handler wywołany z poziomu handler'a zwraca prawidłową nazwę callback'a, co oznaczałoby że ma dostęp do bieżącego stosu handler'ów
3. throw ostatecznie się wykonuje i dopiero domyślny handler kończy działanie
4. użycie restore_exception_handler poza handler'em daje oczekiwany rezultat

Nie wiem zatem czy jest to problem języka, mojej interpretacji zachowania tych funkcji, czy rodzaj zabezpieczenia przed pętlą wyjątków. W dodatku myślę, że w przypadku error'ów może dziać się analogicznie.
Macie może jakieś sugestie, dlaczego wyjątek nie trafia do poprzedniego handler'a? Jakieś alternatywy dla tej funkcjonalności (poza wywoływaniem unknown na końcu catchable)?

A komu to potrzebne?
Sam fragment kodu to oczywiście koncepcja. Zamiarem jest, aby każda klasa, w której będzie to potrzebne, posiadała odrębny handler, w którym obsługiwane będą wyjątki związane z tą klasą. Natomiast główny handler aplikacji wyłapywałby wszystkie pozostałe wyjątki, tak aby zakończyć działanie w bardziej wdzięczny sposób, niż robi to domyślny handler.

EDIT: Znalazłem jeszcze notatkę sprzed 5 lat. Jak zatem rozwiązujecie obsługę wyjątków i błędów w aplikacji, tak aby handling był rozproszony? Gotta catch 'em all? (IMG:style_emoticons/default/tongue.gif)

Ten post edytował session 17.04.2019, 02:38:07
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 5)
viking
post
Post #2





Grupa: Zarejestrowani
Postów: 6 380
Pomógł: 1116
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


A czemu nie zrobisz tego po prostu w odpowiednich namespace? jeśli pakiet to Cos, to klasy wyjątków w Cos\Exception. Łapanie wszystkich będzie pewnie i tak na poziomie index.php, a reszta tam gdzie wywołujesz klasę.
Go to the top of the page
+Quote Post
session
post
Post #3





Grupa: Zarejestrowani
Postów: 112
Pomógł: 22
Dołączył: 11.04.2010
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Nie bardzo wiem jak można by tutaj wykorzystać namespace'y? (IMG:style_emoticons/default/worriedsmiley.gif) Może opiszę to jeszcze od innej strony. Chciałbym zrobić jakiś wygodny exception handling, try/catchowanie tych samych wyjątków w wielu metodach jest dla mnie mało efektywne. W dodatku semantycznie przydatny byłby wielopoziomowy handling:
  1. class Database {
  2. public function __construct(){
  3. set_exception_handler([$this, 'exceptionHandler']);
  4. }
  5.  
  6. public function select(){}
  7. public function insert(){}
  8. public function update(){}
  9. public function delete(){}
  10.  
  11. public function exceptionHandler($e){
  12. restore_exception_handler();
  13. throw $e;
  14. }
  15. }
  16.  
  17. class User {
  18. public function __construct(){
  19. set_exception_handler([$this, 'exceptionHandler']);
  20. }
  21.  
  22. public function add(){ $db = new Database(); $db->insert(); }
  23.  
  24. public function exceptionHandler($e){
  25. restore_exception_handler();
  26. throw $e;
  27. }
  28. }
  29.  
  30. set_exception_handler('unknown');


I wtedy wszystkie wyjątki związane z bazą danych obsługiwane w klasie Database, a wyjątki z klasy User z fallback'iem do Database. Finalnie wszystkie pozostałe wyjątki obsługiwane przez kolejny handler.
Teoretycznie myślę, że można by zrobić customowy stos handler'ów, callback'i, metody set i restore i wykorzystać tylko jeden "oryginalny" handler, ale czy nie byłby to pewnego rodzaju overkill?
Dziwi mnie, że PHP który na kilku stronach manual'a pokazuje wykorzystanie wielu set i restore w tym przypadku nie działa w oczekiwany sposób. (IMG:style_emoticons/default/blink.gif)

Ten post edytował session 17.04.2019, 11:23:30
Go to the top of the page
+Quote Post
viking
post
Post #4





Grupa: Zarejestrowani
Postów: 6 380
Pomógł: 1116
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


Tak z ciekawości. Jak w tej swojej klasie database obsłużysz np transakcje i rollbacki? W klasie User nie powinieneś tworzyć obiektu Database tylko go wstrzyknąć. Bardziej mi to wygląda na problem z architekturą tej aplikacji.
Go to the top of the page
+Quote Post
session
post
Post #5





Grupa: Zarejestrowani
Postów: 112
Pomógł: 22
Dołączył: 11.04.2010
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Ok, nie najlepszy przykład może, tak na prawdę Database byłaby singleton'em i bardziej statyczna, ale wtedy konstruktor nie miałby sensu, więc trochę dla uproszczenia poszedłem na skróty na potrzeby przykładu (IMG:style_emoticons/default/wink.gif) Jednak dalej zastanawiają mnie te wyjątki, tym bardziej, że PHP od 7. wersji coś w tej tematyce ogólnie zmieniał.

Ten post edytował session 17.04.2019, 12:19:44
Go to the top of the page
+Quote Post
viking
post
Post #6





Grupa: Zarejestrowani
Postów: 6 380
Pomógł: 1116
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


https://www.php.net/manual/en/language.errors.php7.php
Możesz wiele wyjątków na raz przez | łapać. Na pewno nie żaden singleton i na pewno nie więcej statyków tylko dependency injection. A czepiam się tego bo wyraźnie to pokazuje że masz problem z architekturą całości i prawidłowym grupowaniem funkcjonalności w zestaw klas.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 22:38