2009-07-31 9 views
15

Wszyscy tu powinien znać „lub” statemens zwykle przyklejone do matrycy() polecenie:PHP: Instrukcja "lub" w przypadku niepowodzenia instrukcji: jak wyrzucić nowy wyjątek?

$foo = bar() or die('Error: bar function return false.'); 

Najbardziej czasów widzimy coś takiego:

mysql_query('SELECT ...') or die('Error in during the query'); 

Jednak nie mogę zrozumieć jak dokładnie działa ta "lub" instrukcja.

chciałbym rzucać nowy wyjątek zamiast matrycy(), ale:

try{ 
    $foo = bar() or throw new Exception('We have a problem here'); 

robi praca, ani

$foo = bar() or function(){ throw new Exception('We have a problem here'); } 

Jedynym sposobem znalazłem na to jest to straszne myśli:

function ThrowMe($mess, $code){ 
    throw new Exception($mess, $code); 
} 
try{ 
    $foo = bar() or ThrowMe('We have a problem in here', 666); 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Ale istnieje sposób, aby rzucić nowy wyjątek bezpośrednio po stwierdzeniu "lub"?

Albo tego rodzaju konstrukcji jest obowiązkowe (dont liek funkcję ThrowMe na wszystkie):

try{ 
    $foo = bar(); 
    if(!$foo){ 
     throw new Exception('We have a problem in here'); 
    } 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Edit: co chcę jest naprawdę, aby uniknąć korzystania z if() sprawdza każdy potencjalny niebezpieczna operacja to zrobić, na przykład:

#The echo $e->getMessage(); is just an example, in real life this have no sense! 
try{ 
    $foo = bar(); 
    if(!$foo){ 
     throw new Exception('Problems with bar()'); 
    } 
    $aa = bb($foo); 
    if(!$aa){ 
     throw new Exception('Problems with bb()'); 
    } 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#But i relly prefer to use something like: 

try{ 
    $foo = bar() or throw new Exception('Problems with bar()'); 
    $aa = bb($foo) or throw new Exception('Problems with bb()'); 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#Actually, the only way i figured out is: 

try{ 
    $foo = bar() or throw new ThrowMe('Problems with bar()', 1); 
    $aa = bb($foo) or throw new ThrowMe('Problems with bb()', 2); 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#But i'll love to thro the exception directly instead of trick it with ThrowMe function. 
+0

Czy chodziło Ci '$ foo' w ostatnim bloku kodu? –

+0

Przepraszam, tak .. mój zły – Strae

Odpowiedz

27

or tylko logical operator, i to jest analogiczne do ||.

Wspólna trick

mysql_query() or die(); 

może równie dobrze być napisane

mysql_query() || die(); 

Co się dzieje tutaj jest „logiczny lub” operator (Niezależnie od wyboru) stara się ustalić, czy którykolwiek z operandów ocenia na PRAWDA. Oznacza to, że operandy muszą być wyrażeniami, które można rzutować jako wartości logiczne.

Tak, powodem

bar() or throw new Exception(); 

jest nielegalne, dlatego

(boolean)throw new Exception(); 

jest również nielegalne. Zasadniczo proces rzucania wyjątku nie generuje wartości zwracanej, którą operator może sprawdzić.

Ale wywołanie funkcji ma generowania wartości zwracanej przez operatora w celu sprawdzenia (bez wyraźnego zwracana wartość spowoduje int funkcja powrocie NULL który rzuca jak FALSE), który jest dlaczego to działa dla ciebie, kiedy owinąć wyjątkiem rzucania w funkcja.

Nadzieję, że pomaga.

+0

Oczywiście, że mi pomaga - wyjaśnił, dlaczego to nie działa;) – Strae

+1

'lub' nie jest analogiczne do '||'. Ten pierwszy ma niższy priorytet niż przypisanie i porównanie. Ta ostatnia jest wyższa. Jest to bardzo ważne rozróżnienie, ponieważ '$ f = jeden() lub dwa()' działa bardzo różnie od '$ f = jeden() || dwa() '. http://us3.php.net/manual/en/language.operators.precedence.php –

+1

Tak, jest. "Analogiczny" nie oznacza "identyczny". Mimo to, twoje wyjaśnienie jest mile widziane: D –

1

Myślę, że chcesz użyć czegoś podobnego ostatniej konstrukcji, chociaż naprawdę nie ma sensu przy użyciu wyjątków dla że:

$foo = bar(); 
if(!$foo){ 
    echo 'We have a problem in here'; 
} 

Za komentarz - Nie sądzę, że można to zrobić w pojedynczej linii (tj. bez sprawdzania if(!$foo)) i zgadzam się, że metoda wyrzucania wyjątków jest dość okropna. Osobiście wolę jednoznaczność od:

$foo = bar(); 
if(!$foo){ 
    throw new Exception('We have a problem in here'); 
} 

ale to jest osobiste preferencje. Jeśli chcesz mieć jedną linię, myślę, że będziesz musiał skorzystać z opcji funkcji rzucania wyjątków.

Podejrzewam, że to ograniczenie zależy prawdopodobnie od tego, czy PHP obsługuje dynamiczne pisanie, ale może też wywoływać wyniki wywołania funkcji warunkowo, ale nie wyniki z throw.

+0

Nie, nie chcę. Echo jest na przykład, w prawdziwym życiu nigdy nie echo komunikatu o błędzie lub kodu, ale obsługiwać je inaczej. To, czego chcę, to unikanie kontroli if (! $ Foo) za każdym razem. – Strae

+0

OK, zaktualizowałem swoją odpowiedź. –

2

Dlaczego bar() i bb() nie wyrzucają wyjątków? W Wyjątkach PHP pojawiają się bańki, więc nie ma potrzeby wyrzucania wyjątku w funkcji/metodzie, w której wywoływane jest bar()/bb(). Te wyjątki mogą być odrzucane przez bar()/bb(). W przypadku, gdy chcesz rzucić kolejny wyjątek, można po prostu zrobić:

function foo() { 
    try { 
     $bar = bar(); 
    } catch (BarException) { 
     throw new FooException; 
    } 
} 
+0

Tak, masz rację, ale co z, na przykład, funkcjami bazy danych? mysql_query()/pg_query()? Do tego muszę użyć lub sprawdzić if() lub straszną funkcję ThrowMe .. po prostu chcę wiedzieć, czy jest możliwe, że id direclty bez ThrowMe() – Strae

+1

@DaNieL: Można użyć PDO dla dostępu DB, który może wyrzucać wyjątki samemu . –

+1

Cóż, to niemożliwe. Próbowałem tego już jakiś czas temu i nie miałem szans. PHP jest użytecznym narzędziem, ale ma również jeden z najgłupszych parserów i interpretatorów na świecie. –

1

Oto rozwiązanie pojedynczej linii bez dodatkowych funkcji:

if (!($foo = bar())) throw new Exception('We have a problem here'); 
0

Można również utworzyć niestandardową klasę wyjątku i wykorzystywać to metoda statyczna konstruktor zamiast throw new Exception() budowlanych. Klasa

Wyjątek:

class CustomException extends Exception { 
    static public function doThrow($message = "", $code = 0, Exception $previous = null) { 
    throw new Exception($message, $code, $previous); 
    } 
} 

Zastosowanie:

try { 

    $foo = bar() or CustomException::doThrow('Problems with bar()'); 
    $aa = bb($foo) or CustomException::doThrow('Problems with bb()'); 

} catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Note

If you are using PHP 7 and higher - you can rename static method doThrow() to simply throw() , since in PHP 7 and higher it's allowed to use reserved keywords as method names.

1

Rozwiązanie znalazłem, że może zastąpić "or die()" wszędzie jest owinąć rzut z anonimowej funkcji, która zostanie natychmiast wywołana przez call_user_func:

call_user_func(function(){ 
    throw new Exception("ERROR"); 
}); 

Widać, że to działa, wykonując to na manekinie skryptu:

false or call_user_func(function(){throw new Exception("ERROR");}); 
Powiązane problemy