try{...}catch does not throw exception in PHP/Symfony2/PHPImap - php

I am using the ImapMail Library and try to initiate a new Mailbox:
try{
$mailbox = new ImapMailbox($url, $username, $password);
}catch (\Exception $e){
return new Response("fail");
}
But the above try/catch does not work, although symfony gives me this:
Connection error: (is empty)
500 Internal Server Error - Exception
the Stacktrace
in vendor/php-imap/php-imap/src/PhpImap/Mailbox.php at line 67:
protected function initImapStream() {
$imapStream = #imap_open($this->imapPath, $this->imapLogin, $this->imapPassword, $this->imapOptions, $this->imapRetriesNum, $this->imapParams);
if(!$imapStream) {
throw new Exception('Connection error: ' . imap_last_error());
}
return $imapStream;
}
(Direct link to function on github)
It does throw a new Exception, why can't I catch it?
Any hint appreciated!

The reason is very simple. You call only class constructor in try block. If you look into the class source code, you will see that constructor does call nothing.
https://github.com/barbushin/php-imap/blob/master/src/PhpImap/Mailbox.php#L20-L31
It means code throwing exception must be under you try/catch. You have to move it inside try block if you want to catch the exception. I am talking about $mailbox->checkMailbox(). This command throws exception.

Related

Can't catch exceptions in laravel

I have the following situation:
try {
DB::beginTransaction();
$task = new Task();
$task->setTracker("");
//thrown \Symfony\Component\Debug\Exception\FatalThrowableError
DB::commit();
}catch (\Exception $e){
DB::rollBack();
Log::error($e);
//throw $e;
}
I am not entering to the catch area.
Any idea why?
update
This is the error thrown:
[Symfony\Component\Debug\Exception\FatalThrowableError]
Type error: Argument 1 passed to App\Models\Task::setTracker() must be an instance of Carbon\Carbon, integer given, called in /var/www/app/Services/ShareLogic.php on line 60
and will not be catched
Thanks
Catching Throwable did the trick.
Have no idea why?
Anyone does?
It does not catch the exception because you are trying to catch \Exception which Symfony\Component\Debug\Exception\FatalThrowableError does not extend.
Instead try to catch the actual exception by importing it..
use Symfony\Component\Debug\Exception\FatalThrowableError;
And then you can do..
try {
//
} catch(FatalThrowableError e) {
//
}
Edit
Ok, so in addition to the above solution it seems PHP 7+ handles error a bit differently than PHP 5. So try this..
try {
//
} catch(Error $e) {
// This should work
} catch(Throwable $e) {
// This should work as well
}
Symfony's Debug component is much more sophisticated in order to log and report all kinds of errors but take look at this simple example (php 7.1.x):
<?php
class MyUncatchableError extends Exception {}
function myExceptionHandler($e) {
throw new MyUncatchableError('BANG: '.$e->getMessage());
}
set_exception_handler('myExceptionHandler');
$foo = true;
try {
$foo->modify();
} catch (Exception $e) {
echo 'nope';
} catch (MyUncatchableError $e) {
echo 'nope2';
}
What will be the outcome? Well:
Fatal error: Uncaught MyUncatchableError: BANG: Call to a member function modify() on boolean in /in/WJErU:6
Stack trace:
0 [internal function]: myExceptionHandler(Object(Error))
1 {main}
thrown in /in/WJErU on line 6
and you can't catch that exception because you should catch the original.. throwable here, which is Error for this kind of "error". You can catch it by catching "Error" class. And with PHP7 hierarchy it implements Throwable interface, that's why you can't catch it using Exception (because while Exception implements Throwable, Error is no an Exception - see: http://php.net/manual/en/language.errors.php7.php).
And this is true for PHP7+ because with 5.* there was no Throwable nor Error, and doing $foo->modify(); would just stop the script and return a Fatal Error. You can make your own error handler (set_error_handler) and throw an exception there (and Debug component does that for php 5.*) but this method does not work for Fatal Errors. Instead Debug component hooks into script shutdown and reads last error and throws FatalErrorException.
This description may not be completely accurate as I have't dug deeply into Symfony but you can get the idea here.

Why this Exception can not be handled by catch try method

When i initiate a class which does not exist , It throws the error, I Don't want to halted by that error . So i try trycatch method , But it still giving me same error, Can someone explain why this error is not been catched
I tried
try{$obj = new classname();}
catch(Exception $e){ echo 'class does not exist, move on' ;}
Fatal error: Class 'classname' not found in C:\WampDeveloper\Websites\localhost\webroot\index.php on line 4
Can someone explain why this error can not be catched ?
Is their is another way to catch and handle this kind of errors ?
UPDATE
We can catch mysql fatal errors by try catch method , So don't say fatal errors can not be handeled by try catch method
Two ways to solve this, use a autoloader that runs a custom written function for each object that does not exist so you can try to "include" a file on demand.
function autoload($objname){
if(is_readable(($f = '/path/to/class/'.$objname.'.php'))){
include $f;
} else {
throw Exception("$f does not exist");
}
}
spl_autoload_register('autoload');
new classname(); // try to load /path/to/class/classname.php
Or you can upgrade to PHP 7 where the error logic has had little overhaul:
Hierarchy
Throwable
Error
ArithmeticError
DivisionByZeroError
AssertionError
ParseError
TypeError
Exception
So a code like this would work:
try{
$obj = new classname();
} catch(Error $er){
echo 'class does not exist, move on';
} catch(Exception $ex){
echo 'a custom exception has been thrown:' . $ex->getMessage();
} catch(Throwable $t){
// Obsolete code, as Throwables are either Error or Exception, that were caught above.
}

Unable to catch an SQL exception

I have a Database class:
<?php
namespace Database\MySQL;
class Database
{
function __construct(){
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$this->Connection = new mysqli(
"", // Testing with no host
"", // Testing with no user
"", // ... no password
"" // and no DB name
);
}
catch (mysqli_sql_exception $e) {
throw $e;
}
...
?>
But instead of a getting an exception, I get a Fatal error: Fatal error: Uncaught exception 'mysqli_sql_exception' with message 'No database selected' in Database.php.
I have tried the same thing with a simple query:
try {
$this->Connection->query("SET NAMES 'utf87'"); //utf87 just for test
}
catch (mysqli_sql_exception $e) {
throw $e;
}
And I still get Fatal error: Uncaught exception.
Your problem is that you are catching the exception, but then just throwing it again without catching it.
If you replace throw $e; with echo "Caught the exception";, you will see that your script is catching the exception. But because you throw it again, it will result in an error unless you have a higher-level try/catch block or a global exception handler.
Also, as many have pointed out in the comments, you need to be careful of namespaces. You need to use a use statement or refer to \mysqli_sql_exception.

Cannot catch Laravel 4 exception

I'm trying to catch a Laravel exception inside my library.
namespace Marsvin\Output\JoomlaZoo;
class Compiler
{
protected function compileItem($itemId, $item)
{
$boom = explode('_', $itemId);
$boom[0][0] = strtoupper($boom[0][0]);
$className = __NAMESPACE__."\\Compiler\\".$boom[0];
try {
$class = new $className(); // <-- This is line 38
} catch(\Symfony\Component\Debug\Exception\FatalErrorException $e) {
throw new \Exception('I\'m not being thrown!');
}
}
}
This it the exception I'm getting:
file: "C:\MAMP\htdocs\name\app\libraries\WebName\Output\JoomlaZoo\Compiler.php"
line: 38
message: "Class 'Marsvin\Output\JoomlaZoo\Compiler\Deas' not found"
type: "Symfony\Component\Debug\Exception\FatalErrorException"
The name of the class is voluntarily wrong.
Edit 1:
I noticed that if I throw an exception inside the try statement I can catch the exception:
try {
throw new \Exception('I\'d like to be thrown!');
} catch(\Exception $e) {
throw new \Exception('I\'m overriding the previous exception!'); // This is being thrown
}
The problem is that you're trying to catch a FatalErrorException in your class, but Laravel won't let a fatal error get back there; it terminates immediately. If your were trying to catch a different kind of exception, your code would work just fine.
You can catch and handle fatal errors with an App::fatal method in app/start/global.php, but that won't help you deal with the exception from within your library, or to handle it with any specificity. A better option would be to trigger a "catchable" exception (something from Illuminate, for instance), or to throw a custom one based on the condition that you are trying to check.
In your case, if your goal is to deal with undefined classes, here's what I would suggest:
try {
$className = 'BadClass';
if (!class_exists($className)) {
throw new \Exception('The class '.$className.' does not exist.');
}
// everything was A-OK...
$class = new $className();
} catch( Exception $e) {
// handle the error, and/or throw different exception
throw new \Exception($e->getMessage());
}

Handling Exceptions - Fatal error: Uncaught exception 'EppCommandsExceptions' with message 'Command syntax error'

Fatal error: Uncaught exception
'EppCommandsExceptions' with message
'Required parameter missing'
The line in question:
throw new EppCommandsExceptions($result->msg, $codigo);
Why am I having this error on this line?
On EppCommandsExceptions.class.php
I have this class that extends Exception:
class EppCommandsExceptions extends Exception
{
//could be empty.
}
Next, on CommandsController.php I have:
include_once('EppCommandsExceptions.class.php');
and, later, if something bad happens on method1:
throw new EppCommandsExceptions($result->msg, $codigo);
later, on this same controller, another method2 that will run after method1,
I have:
if something goes bad with this too:
throw new EppCommandsExceptions($result->msg, $codigo);
Later I have, for the contact part - method1
try
{
$createdContact = $comandos->createContact($contactoVo);
}
catch(EppCommandsExceptions $e)
{
$error .= 'Error Contact. Cód:'.$e->getCode().' Mensagem:'.$e->getMessage();
}
And later, for domain part: method2
try
{
$createdDomain = $comandos->createDomain($domainVo);
}
catch(EppCommandsExceptions $e)
{
$error .= 'Error Domain. Cód:'.$e->getCode().' Mensagem:'.$e->getMessage();
}
Is it because I'm using the same exception for both methods?
Should I have one Exception class for EACH method? :s
Please advice,
Thanks a lot.
MEM
The exception you throw will only be caught if it's inside a try block.
If it isn't it'll propagate up the call stack, until it is caught in one of the earlier calling functions.
You're getting that fatal error because the exception you throw is never caught, so it's handled by the default unhandled exceptions handler, which emits the fatal error.
Examples:
try
{
$createdContact = $comandos->createContact($contactoVo);
if (error_condition())
throw new EppCommandsExceptions $e;
}
catch(EppCommandsExceptions $e)
{
$error .= 'Error Contact. Cód:'.$e->getCode().' Mensagem:'.$e->getMessage();
}
Throwing the exception directly in the try block is not usually very useful, because you could just as well recover from the error condition directly instead of throwing an exception. This construct becomes more useful, though, if createContact may throw an exception. In this case, you have at some point to catch EppCommandsExceptions to avoid a fatal error.

Categories