2014-07-03 18 views
7

Proste pytanie, ale nie może znaleźć odpowiedzi.PHP Spróbuj złapać całą klasę

Jeśli mam klasę php, czy można zarejestrować obsługę wyjątków dla całej klasy?

Powodem, dla którego chcę to zrobić, jest to, że moja klasa używa obiektów, które są częścią mojego modelu domeny. Metody tego obiektu rzucają bardzo wyraźne wyjątki. Nie chcę, aby te wyjątki powodowały bańki w wyższych klasach, ale zamiast tego chcą przechwytywać wszystkie te wyjątki i generować je jako bardziej ogólny wyjątek, np. DomainLayerException

Chciałbym zatem, aby jeden obszar w mojej klasie przechwycił dowolną liczbę list wyjątków, które definiuję z mojego modelu domeny, i zgłasza je jako bardziej ogólny wyjątek, np.

Obecnie sposób, w jaki to robię, polega na zawijaniu wywołań metod do obiektów domeny w bloku catch catch. To staje się bardzo niechlujne, ponieważ używam coraz więcej obiektów domenowych i ich metod. Byłoby świetnie, aby usunąć te, próbować łapać bloki i obsłużyć je wszystkie w jednym miejscu w klasie, tj. Jeśli wyjątek zostanie rzucony w klasie, jest przechwytywany przez pojedynczą procedurę obsługi zdarzenia zdefiniowaną w klasie

Odpowiedz

8

Można użyć klasy proxy do wykonywania połączeń w imieniu i pozwalają owinąć wyjątek:

class GenericProxy 
{ 
    private $obj; 
    private $handler; 

    public function __construct($target, callable $exceptionHandler = null) 
    { 
     $this->obj = $target; 
     $this->handler = $exceptionHandler; 
    } 

    public function __call($method, $arguments) 
    { 
     try { 
      return call_user_func_array([$this->obj, $method], $arguments); 
     } catch (Exception $e) { 
      // catch all 
      if ($this->handler) { 
       throw call_user_func($this->handler, $e); 
      } else { 
       throw $e; 
      } 
     } 
    } 
} 

$proxy = new GenericProxy($something, function(Exception $e) { 
    return new MyCoolException($e->getMessage(), $e->getCode(), $e); 
}); 
echo $proxy->whatever_method($foo, $bar); 

Wykorzystuje magiczną metodę __call() przechwycić i metoda naprzód wzywa do celu.

0

EDYCJA: Wydaje się, że jest to zły pomysł, ponieważ "set_exception_handler" jest metodą globalną, może skończyć się w całym świecie kłopotów, jeśli wiele klas ustawia się jako globalny handler ". Dzięki @Gaz_Edge za wskazanie go.

Powinieneś zamiast tego spojrzeć na Jack's answer.


Jeśli zrozumiałem, co chciał, i że można użyć set_exception_handler w swojej klasie.

Przykład:

class myClass { 
    public function __construct() { 
     set_exception_handler(array('myClass','exception_handler')); 
    } 

    public function test(){ 
     $mySecondClass = new mySecondClass(); 
    } 

    public static function exception_handler($e) { 
     print "Exception caught in myClass: ". $e->getMessage() ."\n"; 
    } 
} 

class mySecondClass{ 
    public function __construct() { 
     throw new Exception('Exception in mySecondClass'); 
    } 
} 

$myClass = new myClass(); 
$myClass->test(); 

To dałoby: Exception caught in myClass: Exception in mySecondClass

jak ten, to byłoby wyjście twój drugi wyjątek klasy obsługiwane przez pierwszego przewodnika klasy.

Mam nadzieję, że pomoże!

+2

dzięki za odpowiedź. Problem z tym jest set_exception_handler jest metodą globalną. Może skończyć się całym światem problemów, jeśli wiele klas ustawia się jako globalny handler –

+0

@Gaz_Edge absolutnie nie jest dobrym pomysłem, aby go użyć w ten sposób. Lepiej mieć metodę proxy opisaną przez Jacka. –

Powiązane problemy