php try catch not working properly - php

I have code like this:
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = file_get_contents($nbg_xml_url);
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}`
and problem is that, when file_get_contents can not read url (may be site not responding or something like this..) my code writes error: failed to open stream: HTTP request failed! and execution goes direct to finally block bypass catch block without entering in it..
any ideas?

You can set an empty error handler to prevent the warning and afterward throw a custom exception in case of failure. In this case I would write a custom file_get_content like so:
function get_file_contents($url) {
$xml_content = file_get_contents($url);
if(!$xml_content) {
throw new Exception('file_get_contents failed');
}
return $xml_content;
}
and would use it in your block:
set_error_handler(function() { /* ignore errors */ });
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = get_file_contents($nbg_xml_url); //<----------
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}
Then remember to restore the error handler calling:
restore_error_handler();
Note that when using your own error handler it will bypass the
error_reporting
setting and all errors included notices, warnings, etc., will be passed to it.

$xml_content = file_get_contents($nbg_xml_url);
The function file_get_contents does not throw an exception. Thus an exception will not be thrown if as you say the file is not found.
From the docs:
An E_WARNING level error is generated if filename cannot be found...
This function returns the read data or FALSE on failure. So you could check if $xml_content is FALSE ($xml_content === false) and proceed accordingly.

This is a php code for catching any error or exception.
Throwable is the base interface for any object that can be thrown via a throw statement, including Error and Exception.
This will catch fatal errors too. Without throwable it will not catch fatal errors.
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
// Executed only in PHP 5.x, will not be reached in PHP 7
}

Related

When is an exception considered as uncaught? [duplicate]

I know this is a weird on, but in my code, i have development mode errors, and production mode errors. This is the function i have:
private function error($message, $mysql_error = null){
if( DEVELOPMENT_MODE ){
$exp = new Exception();
$trace = $exp -> getTrace();
array_shift( $trace ); // removes this functions from trace
$data["Error Mg"] = $message;
$data["MySQL Er"] = ( is_null ( $mysql_error ) ) ? "" : $mysql_error;
array_unshift($trace, $data );
fkill( $trace ); // formats array and then dies
}
else{
throw new Exception ( $data );
}
}
I wrote this function in my database class, so that if an error happens, I don't have to provide the check if we're in development mode or not!
So I thought I could externalise the re-usable code. However, because I'm throwing an exception from this function, I'm basically just using a function, that will return a thrown error. Pretty useless in production mode.
I would have to do this every time i want to use it:
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
RATHER THAN JUST
$this -> error( "Invalid Link After Connect.", mysql_error () );
so to avoid writing a try ... catch block for every error function I want to call... is there any way to throw the exception 2 levels up?
An exception will automatically travel up the call chain until it reaches the highest level. If it's not caught there, program execution terminates due to an uncaught exception. The whole point of exceptions is to be able to have errors bubble up. You don't need to throw harder or do anything special to "throw it up 2 levels", that's what it does by definition.
Just omit the try/catch block. Exceptions automatically propagate up as far as they can until something catches them; you don't need to explicitly re-throw them at every level of the call stack.
This...
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
is exactly equivalent to this:
$this -> error( "Invalid Link After Connect.", mysql_error () );
Use Multiple catch Blocks
use admin table which has field
Mode Value
0 Production
1 Debug
the first catch which matches the exception is executed
Example
try {
if (!$bDBConnection && $row['mode'] ==0 ) {
throw new Produciton_DBException("Problem with Database");
}
else
{
throw new Debug_DBException("Problem with Database");
}
}
catch(Produciton_DBException $e)
{
// display suitable error messages
}
catch(Debug_DBException $ex)
{
// Exception falls through until a match is found
}

libcouchbase connection errors

Couchbase keeps complaining that I don't have a connection to Couchbase:
2013-10-28T11:15:46.580320-07:00 hoot77 apache2[30455]: PHP Warning: There is no active connection to couchbase in /ebs1/www/src/core/components/In/Couchbase/Bucket.php on line 112
The following is the piece of code that is trying to run, its a simple set.
*/
public function set($key, $doc, $try = 0) {
// Make sure designDoc and dataView are set
if(empty($this->designDoc) && empty($this->dataView)) {
throw new In_Exception('Missing Design Doc and/or View name for Couchbase', 400);
}
try {
$results = $this->cb->set($key, $doc);
} catch(CouchbaseLibcouchbaseException $e) {
// Connection not active, try to rebuild connection and query again
// Log stats on exception
Statsd::increment("web.Couchbase.Exception.LibCouchbaseException.{$this->instanceKey}");
Logger::error("LibCouchbaseException on {$this->instanceKey}: {$e->getMessage()}");
// Try to reconnect and query up to twice
$try++;
if($try <= 2) {
$this->rebuildConnection();
return $this->set($key, $doc, $try);
} else {
// Fail if we've already tried twice
throw new In_Exception('Could not connect to Couchbase', 500);
}
} catch(CouchbaseException $e) {
// Catch general exception, try to determine cause
// Log stats on exception
Statsd::increment("web.Couchbase.Exception.CouchbaseException.{$this->instanceKey}");
Logger::error("CouchbaseException on {$this->instanceKey}: {$e->getMessage()}");
// Throw exception if design document or view not found
if($this->getExceptionCode($e->getMessage()) == 404) {
throw new In_Exception('Design Document, or View not found in Couchbase', 404);
} else {
throw new In_Exception('Error with Couchbase, try again.', 500);
}
}
// Success, return results
Statsd::increment("web.couchbase.{$this->instanceKey}.success");
return $results;
}
The line that its complaining about is:
$results = $this->cb->set($key, $doc);
You can see that my quick solution was to try to reconnect up to twice on failure, but that doesn't seem to be helping at all, the errors still persist in great numbers.
It's actually not catching the exceptions and reporting them consistently either, which is annoying, because PHP is throwing these as warnings, not exceptions.
Let me know if you have any suggestions as to how to solve this, it would be greatly appreciated. Thanks!

Get all the exceptions from one try catch block

I wonder if it's posible to get all the exceptions throwed.
public function test()
{
$arrayExceptions = array();
try {
throw new Exception('Division by zero.');
throw new Exception('This will never get throwed');
}
catch (Exception $e)
{
$arrayExceptions[] = $e;
}
}
I have a huge try catch block but i want to know all the errors, not only the first throwed. Is this possible with maybe more than one try or something like that or i am doing it wrong?
Thank you
You wrote it yourself: "This will never get throwed" [sic].
Because the exception will never get thrown, you cannot catch it. There only is one exception because after one exception is thrown, the whole block is abandoned and no further code in it is executed. Hence no second exception.
Maybe this was what the OP was actually asking for. If the function is not atomic and allows for some level of fault tolerance, then you can know all the errors that occurred afterwards instead of die()ing if you do something like this:
public function test()
{
$arrayExceptions = array();
try {
//action 1 throws an exception, as simulated below
throw new Exception('Division by zero.');
}
catch (Exception $e)
{
//handle action 1 's error using a default or fallback value
$arrayExceptions[] = $e;
}
try {
//action 2 throws another exception, as simulated below
throw new Exception('Value is not 42!');
}
catch (Exception $e)
{
//handle action 2 's error using a default or fallback value
$arrayExceptions[] = $e;
}
echo 'Task ended. Errors: '; // all the occurred exceptions are in the array
(count($arrayExceptions)!=0) ? print_r($arrayExceptions) : echo 'no error.';
}

Cleanest way to execute code outside of try block only if no exception is thrown

This question is about the best way to execute code outside of try block only if no exception is thrown.
try {
//experiment
//can't put code after experiment because I don't want a possible exception from this code to be caught by the following catch. It needs to bubble.
} catch(Exception $explosion) {
//contain the blast
} finally {
//cleanup
//this is not the answer since it executes even if an exception occured
//finally will be available in php 5.5
} else {
//code to be executed only if no exception was thrown
//but no try ... else block exists in php
}
This is method suggested by #webbiedave in response to the question php try .. else. I find it unsatisfactory because of the use of the extra $caught variable.
$caught = false;
try {
// something
} catch (Exception $e) {
$caught = true;
}
if (!$caught) {
}
So what is a better (or the best) way to accomplish this without the need for an extra variable?
One possibility is to put the try block in a method, and return false if an exception is cought.
function myFunction() {
try {
// Code that throws an exception
} catch(Exception $e) {
return false;
}
return true;
}
Have your catch block exit the function or (re)throw/throw an exception. You can filter your exceptions as well. So if your other code also throws an exception you can catch that and (re)throw it. Remember that:
Execution continues if no exception is caught.
If an exception happens and is caught and not (re)throw or a new one throw.
You don't exit your function from the catch block.
It's always a good idea to (re)throw any exception that you don't handle.
We should always be explicit in our exception handling. Meaning if you catch exceptions check the error that we can handle anything else should be (re)throw(n)
The way I would handle your situation would be to (re)throw the exception from the second statement.
try {
$this->throwExceptionA();
$this->throwExceptionB();
} catch (Exception $e) {
if($e->getMessage() == "ExceptionA Message") {
//Do handle code
} elseif($e->getMessage() == "ExceptionB Message") {
//Do other clean-up
throw $e;
} else {
//We should always do this or we will create bugs that elude us because
//we are catching exception that we are not handling
throw $e;
}
}

How to set a HTTP_Exception_404

I am using kohana 3.2 and kohana-error module is working fine, when the page does not exist.
But I have this situation: the page exist, but no data is coming, because the data does not exist. I am using the route param to check de database.
So I did this,
if($response )
{
return $response;
} else {
throw new HTTP_Exception_404('Page Not Found');
}
If there are data return, if not, create a ‘Page Not Found’ and I supose it will be caught by the kohana-error module but it is not....
Is that possible? Is this the right approach?
In your index.php, you do the following:
$request = Request::factory();
try
{
$response = $request->execute();
if (!$response->body())
{
throw new HTTP_Exception_404();
}
}
catch (Exception $exc)
{
if ($exc instanceof HTTP_Exception_404)
{
$response = Request::factory('your/404error/controller')->execute();
}
else
{
// rethrow exception
throw $exc;
}
}
echo
$response
->send_headers()
->body();
That way, you can execute a controller for each HTTP exception, or you can use a catch all 404 page for all exceptions (50x and 40x errors)

Categories