PHP: declaração 'ou' na instrução falhar: como lançar uma nova exceção?
-
06-07-2019 - |
Pergunta
Todos aqui devem conhecer os statemens 'ou', normalmente colada a uma die () comando:
$foo = bar() or die('Error: bar function return false.');
A maioria das vezes nós vemos algo como:
mysql_query('SELECT ...') or die('Error in during the query');
No entanto, eu não consigo entender como exatamente isso 'ou' obras de instrução.
Gostaria de lançar uma nova exceção em vez de die (), mas:
try{
$foo = bar() or throw new Exception('We have a problem here');
não funciona, e nem
$foo = bar() or function(){ throw new Exception('We have a problem here'); }
A única maneira que eu encontrei para fazer isso é esse pensamento horrível:
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();
}
Mas há uma maneira de lançar uma nova exceção logo após o 'ou' declaração?
Ou este tipo de estrutura é obrigatória (eu não liek a função ThrowMe em tudo):
try{
$foo = bar();
if(!$foo){
throw new Exception('We have a problem in here');
}
}catch(Exception $e){
echo $e->getMessage();
}
Editar : o que eu quero realmente é para evitar o uso de um if () verificar cada potencial operação perigosa eu faço, por exemplo:
#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.
Solução
or
é apenas um lógica operador, e é análoga para ||
.
O truque comum de
mysql_query() or die();
poderia muito bem ser escrita ??p>
mysql_query() || die();
O que acontece aqui é o operador "ou lógico" (o que você escolher) está tentando determinar se o operando é avaliado como true. Isto significa que os operandos devem ser expressões que podem ser expressos como um boolean.
Assim, a razão
bar() or throw new Exception();
é ilegal, é porque
(boolean)throw new Exception();
também é ilegal. Em essência, o processo de lançar uma exceção não gera um valor de retorno para o operador para verificar.
Mas chamar uma função faz gerar um valor de retorno para o operador verificar (sem valor de retorno explícita resultará int a função retornando NULL
que lança como FALSE
) é por isso que ele funciona para você quando você envolvê lançando exceção em uma função.
Espero que ajude.
Outras dicas
Por que não bar()
e bb()
jogar as exceções? Em PHP Exceções borbulhar, por isso não há necessidade de lançar a exceção na função / método onde você chamar bar()
/ bb()
. Essas exceções podem ser lançadas por bar()
/ bb()
. No caso de você querer jogar outra exceção, você pode simplesmente fazer:
function foo() {
try {
$bar = bar();
} catch (BarException) {
throw new FooException;
}
}
A solução que eu encontrei que pode substituir "ou die ()" em todos os lugares é envolver o arremesso com uma função anônima que é chamada imediatamente por call_user_func:
call_user_func(function(){
throw new Exception("ERROR");
});
Você pode ver que ele funciona, executando isso em um script fictício:
false or call_user_func(function(){throw new Exception("ERROR");});
Eu acho que você quer usar algo como a última estrutura, embora não há realmente nenhum ponto em usar exceções para isso:
$foo = bar();
if(!$foo){
echo 'We have a problem in here';
}
Por comentário - Eu não acho que você pode fazer isso em uma única linha (ou seja, sem a verificação if(!$foo)
), e eu concordo que o método de exceção de arremesso é bastante horrível. Pessoalmente, eu prefiro a explicitação de:
$foo = bar();
if(!$foo){
throw new Exception('We have a problem in here');
}
mas isso é uma preferência pessoal. Se você quiser a coisa de uma única linha, eu acho que você vai ter que ir com a sua opção de função de arremesso de exceção.
Eu acho que essa limitação é provavelmente baixo para coisas dynamic-digitação de PHP, ele pode lançar os resultados de uma chamada de função para uma condicional, mas não os resultados de um throw
.
Aqui está uma solução de linha única, sem a função extra:
if (!($foo = bar())) throw new Exception('We have a problem here');
Eu simplesmente definida a função toss
para isso.
function toss(Exception $exception): void
{
throw $exception;
}
Porque a linha / informações do arquivo / pilha é capturada quando a exceção é construído (new
) não lançada (throw
) esta não interfere com a pilha de chamadas.
Assim, você pode simplesmente fazer isso.
something() or toss(new Exception('something failed'));
Você também pode criar uma classe de exceção personalizada e usá-lo de método construtor estático em vez de construção throw new Exception()
.
classe Exceção:
class CustomException extends Exception {
static public function doThrow($message = "", $code = 0, Exception $previous = null) {
throw new Exception($message, $code, $previous);
}
}
Uso:
try {
$foo = bar() or CustomException::doThrow('Problems with bar()');
$aa = bb($foo) or CustomException::doThrow('Problems with bb()');
} catch(Exception $e){
echo $e->getMessage();
}
Nota ??strong>
Se você estiver usando PHP 7 e superior -. Você pode renomear método
doThrow()
estática simplesmentethrow()
, já que em PHP 7 e superior é permitido o uso de palavras-chave reservadas como nomes de métodos