2009-07-31 6 views
15

Tutti qui dovrebbe conoscere le 'o' statemens, di solito incollati a un die() comando:PHP: errore "o" sull'istruzione fallita: come lanciare una nuova eccezione?

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

La maggior parte delle volte si vede qualcosa di simile:

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

Tuttavia, Non riesco a capire come funziona esattamente questa affermazione "o".

vorrei lanciare una nuova eccezione invece di morire(), ma:

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

non lavorare, e nessuno dei due

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

L'unico modo che ho trovato per farlo è questa orribile pensato:

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(); 
} 

Ma c'è un modo per lanciare una nuova eccezione direttamente dopo l'istruzione "o"?

O questo tipo di struttura è obbligatoria (I dont liek la funzione ThrowMe a tutti):

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

Edit: quello che voglio è proprio quello di evitare l'uso di un caso() controllare ogni potenziale un'operazione pericolosa che faccio, per esempio:

#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

Forse intendevi '$ foo' nel tuo ultimo blocco di codice? –

+0

Mi spiace, sì ... il mio male – Strae

risposta

27

or è solo un logical operator, ed è analogo a ||.

Il trucco comune di

mysql_query() or die(); 

potrebbe altrettanto bene essere scritto

mysql_query() || die(); 

quello che succede qui è l'operatore "logica o" (a seconda di quale si sceglie) sta cercando di determinare se uno degli operandi valuta a VERO. Ciò significa che gli operandi devono essere espressioni che possono essere espresse come booleane.

Quindi, la ragione

bar() or throw new Exception(); 

è illegale, è perché

(boolean)throw new Exception(); 

è anche illegale. In sostanza, il processo di lancio di un'eccezione non genera un valore di ritorno da controllare per l'operatore.

Ma chiamare una funzione fa generare un valore di ritorno per l'operatore a controllare (nessun valore di ritorno esplicito risulterà int la funzione che restituisce NULL che getta come FALSE) ed è per questo che funziona per voi quando si avvolgono eccezione gettando in una funzione.

Spero che questo aiuti.

+0

Certo che mi aiuta - ha spiegato perché non funziona;) – Strae

+1

'or' non è analogo a' || '. Il primo ha precedenza inferiore rispetto all'assegnazione e al confronto. Quest'ultimo ha più alto. Questa è una distinzione molto importante perché '$ f = one() o two()' funziona in modo molto diverso da '$ f = one() || due() '. http://us3.php.net/manual/en/language.operators.precedence.php –

+1

Sì, lo è. "Analogo" non significa "identico". Detto questo, il tuo chiarimento è il benvenuto: D –

1

Penso che si desidera usare qualcosa come l'ultima struttura, anche se non c'è davvero alcun senso usare le eccezioni per questo:

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

Per commento - non credo che si può fare in una sola riga (vale a dire senza il controllo if(!$foo)) e sono d'accordo sul fatto che il metodo di lancio delle eccezioni sia piuttosto orribile. Personalmente, preferisco la chiarezza di:

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

ma questa è una preferenza personale. Se vuoi la cosa a linea singola, penso che dovrai utilizzare l'opzione di lancio della tua eccezione.

Immagino che questa limitazione sia probabilmente dovuta alle funzionalità di digitazione dinamica di PHP, può trasmettere i risultati di una chiamata di funzione a un condizionale, ma non i risultati di un throw.

+0

No, non voglio. L'eco è solo per esempio, nella vita reale non riecheggia mai il messaggio di errore o il codice, ma gestiscili diversamente. Quello che voglio è esattamente evitando il controllo if (! $ Foo) ogni volta. – Strae

+0

OK, ho aggiornato la mia risposta. –

2

Perché non bar() e bb() lanciare le eccezioni? In PHP Eccezioni bolla, quindi non c'è bisogno di buttare l'eccezione nella funzione/metodo in cui si chiama bar()/bb(). Tali deroghe possono essere lanciate da bar()/bb(). Nel caso in cui si vuole buttare un'altra eccezione, si può semplicemente fare:

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

Sì, amico, ma, per esempio, il database funziona? mysql_query()/pg_query()? Per questi devo usare o il controllo if(), o la funzione orribile di ThrowMe .. voglio solo sapere se è possibile fare id direclty senza ThrowMe() – Strae

+1

@DaNieL: Potresti usare PDO per l'accesso a DB che può generare eccezioni stessa . –

+1

Beh, non è possibile. L'ho provato io stesso qualche tempo fa e nessuna possibilità. PHP è uno strumento utile, ma ha anche uno dei più stupidi parser e interpreti al mondo. –

1

Ecco una soluzione single-line senza la funzione in più:

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

È possibile anche creare una classe di eccezione personalizzata e utilizzare è il metodo costruttore statico invece di throw new Exception() costruzione. Classe

Eccezione:

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

Usage:

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

Una soluzione che ho trovato che può sostituire "or die()" in tutto il mondo è quello di avvolgere il tiro con una funzione anonima che viene chiamato immediatamente da call_user_func:

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

Si può vedere che funziona eseguendo questo su uno script dummy:!

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