PHP finally clause - php

What is the best practice to simulate a finally clause? I realize this could be considered related (though I don't think it's a duplicate) of this question.
However, in my case I want to handle exceptions, I want to use finally (or whatever PHP equivalent or practice) as defined by python:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not.
Just loosely writing the code after the try-catch block seems like an ugly practice to me.

In the RFC for adding finally to PHP, they suggest this workaround:
<?php
$db = mysqli_connect();
try {
call_some_function($db);
} catch (Exception $e) {
mysqli_close($db);
throw $e;
}
mysql_close($db);
So unless you upgrade to PHP 5.5 (which will contain the finally construct), this is probably your best option.

This could be considered something of a non-answer, but there are ways of structuring code that mean finally is not needed, such as the "RAII Pattern" ("Resource Acquisition Is Initialization") where cleanup of a resource is done in the destructor of a locally scoped variable representing that resource.
The idea is that if an exception rips you out of function scope, your destructor will fire, so your cleanup happens as expected. If no exception is thrown, you will reach the end of your function, and your variable will go out of scope that way.
A quick Google turned up this simple code for doing it with arbitrary callbacks.

PHP 5.5 and later do have the finally construct.
From the docs:
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}

If you are still stuck maintaining pre 5.5 legacy code, and you don't mind the overhead of a mandatory fake throw every call, there is always this dirty little trick.
try {
// do your worst to mess things up.
throw new Exception("finally");
} catch (Exception $e) {
//TODO: after upgrading to 5.5, make this a legit try/catch/finally
if ( ($msg = $e->getMessage()) != "finally"){
// real catch
echo "Exception doing something :" . $msg;
} else {
// quasi finally.
};
}

Related

Understanding try and catch

This probably sounds ridiculous. However, if you don't ask you'll never learn.
I'm relatively new to PHP and self-taught so I haven't exactly learnt everything "to the book".
Is the following required:
try {
}
catch {
}
Am I right in thinking that the try will try to "execute" the code within the brackets and the catch will try and catch the result of the outcome? If there is nothing to catch then it will throw an error?
The first assumption is correct: the code in try will be attempted to run.
However, if no error is thrown, then the block exits normally. If there is an error thrown, then the try execution ends early and goes into the catch block. So your second idea is switched.
try catch is used for exception handling or error handling.Put your script in try block and write your custom error message in catch block.
try{
// put here script
}catch(Exception $error){
//your custom message
echo 'Caught exception: ', $error->getMessage(), "\n";
}
If your script does not execute then it will be jump catch block and access message using $error object.
What is the benefit? The benefit is the whole script will not be stop to execute. It will be continue other block.
In the try block you execute code, whenever something fails in that block it will jump to the catch block. You usually define a variable holding the exception.
So to answer your question, no it will not process the catch block when there is nothing going wrong in the try block. (unless you specifically throw an exception)
try {
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Try block is hold the code which you want to execute. and Catch block is hold the code if you have cause any error then it will execute the catch code or error message.
Basically try and catch we are using for the error handling and avoid to break the control flow of the program and page.
Simple example:
<?php
class A {
public function getA($a = 0)
{
if ($a === 0) {
throw new ItCantBeZeroException("Message");
}
return $a;
}
}
// I want to throw default exception because I'm not sure
// am I doing it right or what can I do with bad parameter.
$a = new A;
echo $a->getA(0);
// Now, I know what I can do if developer write bad input.
// It can't be 0, so I just print my custom error message
// to my page.
try {
$a = new A;
echo $a->getA(0);
} catch (ItCantBeZeroException $e) {
echo "Parameter can't be zero. Try again.";
}
?>
You can define your own exceptions (like ItCantBeZeroException). Exceptions throw error on site (like "Message") but we can catch them and change to something we want.
You write simple class where some code must be string or integer between 0 and 20.
You use this code, but when user make variable 21, simple class throw error.
You refactor code to catch exception and try to fix code, e.g. change any integer greater than 20 to 20. Then code works properly.
Try and Catch is known as Exception Handling
According to w3schools:
Exceptions Handling are used to change the normal flow of a script if a specified error occurs.
For More:
http://www.w3schools.com/php/php_exception.asp

catch an exception an throw another one... is there any other way?

In Laravel framework whenever you try to fetch some data from your eloquent model, if an exception occurs, it'll throw aModelNotFoundException. In my project I need to catch this exception and redirect user to specific route.
the solution that I've ended up is like this:
try{
$foundUser = $this->user->whereId($id)->firstOrFail();
}catch(ModelNotFoundException $e){
throw new NonExistantUserException;
}
I know that I can put my redirect code inside the catch block, however I'm already catching these sort of exceptions in global.php:
App::error(function(NonExistantUserException $e)
{
return Redirect::back()->WithInput();
});
I want to know is there any way to say, for example no matter what kind of exception would occur inside try block I want to catch it as NonExistantUserException just for this try block!
I'm asking because catching an exception an throw another one. seems a bad practice to me.
Thanks in advanced.
Absolutely not bad practice and even common practice. But you should not simply discard the previous exception as it might be useful for debugging purposes.
<?php
try {
$foundUser = $this->user->whereId($id)->firstOrFail();
} catch (ModelNotFoundException $e) {
throw new NonExistentUserException(
"Could not find user for '{$id}'.",
null,
$e // Keep previous exception.
);
}
This ensures that you have the full chain of exceptions at your disposal. Other than that your approach looks good to me.

Programming without "finally"

I don't have the required version of PHP that supports finally, so I am wondering if this:
try {
work();
} catch (Exception $e) {
cleanup();
throw $e;
}
cleanup();
is exactly the same as
try {
work();
} finally {
cleanup();
}
The point of the finally block is to execute regardless of what happens in the try block, or in following catch cases. So if you think about it, the code in the finally block is executed either after a successful try block execution, or after any exception was thrown. So if you write it just as you did in your solution, then you do indeed mimic the situation exactly. If there is no exception, the code after the try/catch structure is executed; and if there is an exception—any exception—you also execute it.
I think the only situation which the finally support may rescue you from, which your version inherently can’t, is when you are actually aborting the outer execution stack early. For example if this code is inside a function and you are returning from within the try block, then the finally would still be executed, but in your manual implementation it of course couldn’t.
So if you make sure that you do not leave early, then yes, it should work in the same way.
There are not many ways to leave a function early that don’t throw an exception; return is the most obvious and aborting the program with exit, die or similar would be another.
Finally code blocks execute always - if there's an exeption, and if there isn't. But if you catch an exeption and do cleanup() after catch block, then yes - it's basically the same thing.
From the PHP docs:
In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
If you look at the examples, you'll notice that the finally block will always execute even if the exception is caught. However, when there is an exception, the code will not resume, so the finally block is a good way to ensure that certain lines of code are always executed even if there is an exception.
The finally block will matter if your catch block uses a return function or something like that. Otherwise, there is no difference between putting your cleanup in the finally block or after your try/catch
Here's the example in question from the doc comments:
Just an example why finally blocks are usefull (5.5)
<?php
//without catch
function example() {
try {
//do something that throws an exeption
}
finally {
//this code will be executed even when the exception is executed
}
}
function example2() {
try {
//open sql connection check user as example
if(condition) {
return false;
}
}
finally {
//close the sql connection, this will be executed even if the return is called.
}
}
?>
Generally, yes.
Most of times, both examples work equivalently:
<?php
function work_success() {
echo 'working' . PHP_EOL;
}
function work_fail() {
echo 'working with fail' . PHP_EOL;
throw new Exception('exception');
}
function cleanup() {
echo 'cleanup' . PHP_EOL;
}
Code without finally:
try {
work();
} catch (Exception $e) {
cleanup();
throw $e;
}
cleanup();
Code with finally:
try {
work();
} finally {
cleanup();
}
Results when work = work_success for both finally and non-finally versions:
working
cleanup
Results when work = work_fail for both finally and non-finally versions:
working
cleanup
Exception: exception
However, there are caveats.
Like #poke said, using your examples together with control flow mechanisms might get funny results. Here's an illustration of this using simple return statement:
function test()
{
try {
return 'success';
} catch (Exception $e) {
cleanup();
throw $e;
}
cleanup();
}
echo test();
This will output just success. cleanup() won't get fired unless an exception is thrown. According to prior examples, equivalent finally counterpart to above example would look like this:
function test()
{
try {
return 'success';
} finally {
cleanup();
}
}
echo test();
Note that this will execute cleanup() regardless of any exceptions, so the output will be:
cleanup
success
For some people it's suprising that code in finally block is executed prior to return statements. As long as you are aware of this, there should be no problems.

PHP 5.5 and try ... finally

PHP 5.5 is adding support for finally in try/catch blocks.
Java allows you to create a try/catch/finally block with no catch block, so you can cleanup locally when an exception happens, but let the exception itself propagate up the call stack so it can be dealt with separately.
try {
// Do something that might throw an exception here
} finally {
// Do cleanup and let the exception propagate
}
In current versions of PHP you can achieve something that can do cleanup on an exception and let it propagate, but if no exception is thrown then the cleanup code is never called.
try {
// Do something that might throw an exception here
} catch (Exception $e) {
// Do cleanup and rethrow
throw $e;
}
Will PHP 5.5 support the try/finally style? I have looked for information on this, but the closest I could find to an answer, from PHP.net, only implies that it doesn't.
In PHP 5.5 and later, a finally block may also be specified after the
catch blocks. Code within the finally block will always be executed
after the try and catch blocks, regardless of whether an exception has
been thrown, and before normal execution resumes.
The wording suggests that you're always expected to have a catch block, but it doesn't state it outright as far as I can see.
Yes, try/finally is supported (RFC, live code). The documentation is indeed not very clear and should be amended.
I've implemented a test case on a 5.5RC3 server.
As you can see in the code, it works as expected. Documentation is indeed wrong at this point.

Why should I use exception handling in php?

I've been programming PHP for a long time, but not so much PHP 5... I've known about exception handling in PHP 5 for some time, but never really looked into it. After a quick Google it seems fairly pointless to use exception handling - I can't see the advantages of using it over just using some if() {} statements, and perhaps my own error handling class or whatever.
There's got to be a bunch of good reasons for using it (I guess?!) otherwise it wouldn't have been put into the language (probably). Can anyone tell me of some good benefits it has over just using a bunch of if statements or a switch statement or something?
Exceptions allow you to distinguish between different types of errors, and is also great for routing. For example...
class Application
{
public function run()
{
try {
// Start her up!!
} catch (Exception $e) {
// If Ajax request, send back status and message
if ($this->getRequest()->isAjax()) {
return Application_Json::encode(array(
'status' => 'error',
'msg' => $e->getMessage());
}
// ...otherwise, just throw error
throw $e;
}
}
}
The thrown exception can then be handled by a custom error handler.
Since PHP is a loosely typed language, you might need to ensure that only strings are passed as arguments to a class method. For example...
class StringsOnly
{
public function onlyPassStringToThisMethod($string)
{
if (!is_string($string)) {
throw new InvalidArgumentException('$string is definitely not a string');
}
// Cool string manipulation...
return $this;
}
}
...or if you need to handle different types of exceptions in different ways.
class DifferentExceptionsForDifferentFolks
{
public function catchMeIfYouCan()
{
try {
$this->flyForFree();
} catch (CantFlyForFreeException $e) {
$this->alertAuthorities();
return 'Sorry, you can\'t fly for free dude. It just don\'t work that way!';
} catch (DbException $e) {
// Get DB debug info
$this->logDbDebugInfo();
return 'Could not access database. What did you mess up this time?';
} catch (Exception $e) {
$this->logMiscException($e);
return 'I catch all exceptions for which you did not account!';
}
}
}
If using transactions in something like Zend Framework:
class CreditCardController extends Zend_Controller_Action
{
public function buyforgirlfriendAction()
{
try {
$this->getDb()->beginTransaction();
$this->insertGift($giftName, $giftPrice, $giftWowFactor);
$this->getDb()->commit();
} catch (Exception $e) {
// Error encountered, rollback changes
$this->getDb()->rollBack();
// Re-throw exception, allow ErrorController forward
throw $e;
}
}
}
Exception handling: If condition versus Exception isn't specific to PHP, but gives a good perspective. Personally, Exception(s) & try/catch are implemented in languages to enforce good behaviour amongst developers that normally wouldn't be as attentive to error checking / handling.
If you are confident that your if/else if/else is catching all scenarios, than cool.
Here is an overview of the Advantages of Exceptions - Java -- At one point, there is a snippet of code that has many if/else statements and the following excerpt:
There's so much error detection, reporting, and returning here that the original seven lines of code are lost in the clutter. Worse yet, the logical flow of the code has also been lost, thus making it difficult to tell whether the code is doing the right thing: Is the file really being closed if the function fails to allocate enough memory? It's even more difficult to ensure that the code continues to do the right thing when you modify the method three months after writing it. Many programmers solve this problem by simply ignoring it — errors are reported when their programs crash.
So really, it comes down to personal preference in the end. If you want code that is readable and can be consumed by other people, it's generally a better approach and enforces best-behaviour
If you are following the object-oriented methodology then exceptions comes handy for the error handling. It is convenient to communicate the errors through exception across the objects.
Exceptions are really helpful if you go with layered design approach.
If you are not coding in object-oriented way, then exceptions are not required.
We use exception handling if we are not sure about the code results. We put that snippet of code in try block and catch that error in catch block. Please check this link for more information.
In general there are two good reasons to use exception handling:
You might now always know where an exception will occur - something unexpected could arise. If you use a global exception handler you can make sure that no matter what goes wrong, your program has a chance to recover. Similarly a particularly sensitive piece of code (like something that does I/O) could have all sorts of different errors that can only be detected at runtime and you want to catch any possible contingency. Some things might not occur during testing; like what if a server outside of your control fails? This may never be tested before it really happens (although good testing would include this). This is the more important reason really.
Performance. Typically exceptions are implemented so that everything is fast so long as nothing goes wrong. Exceptions are caught after they occur. This means that no 'if' statement has to be evaluated in advance if something goes wrong, and the overhead is very low in that case. If you don't use exceptions you will be forced to add a lot of 'if' statements to your code. While usually this isn't much of a problem, this can kill a performance-critical application. This is especially true because a branch mis-prediction in the CPU can cause a pipeline flush.
I that reason is that Exception is called after trigger_error(); function and you can send also some additional information to that exception = better debugging?
I'm not sure but I think that's it
example:
class db
{
function connect()
{
mysql_Connect("lolcalhost", "root", "pass:)") or trigger_error("Test");
}
}
try
{
}
catch (db
One of the primary reasons for having an exceptions framework is so that if the code ever gets to the point where it cannot proceed, it has the ability to tell the surrounding context that something has gone wrong. It means that if I have a class Foo which needs to have $fooInstance->setBarHandler($barHandler) called before $fooInstance->doFoo(); can succeed, the class can provide a message to the greater context instead of failing silently and returning FALSE. Further, it allows the context to say, "Huh. That broke. Well, I can now tell the user/logs/something else that something bad happened, and I can decide whether I need to keep on chugging."
Exceptions can provide much more data than simple -1 or false.
Exceptions can do advanced error handling. Keep in mind that try .. catch blocks can be nested and there could be more than one catch block in try .. catch block.
Exceptions force you to handle errors. When you're not using them you do something like:
function doSomething($a, $b, $c) {
...
if ($a < $b && $b > $c) {
return -1; // error
}
...
}
$d = doSomething($x, $y, $z);
if ($d === -1) {
die('Fatal error!');
}
And everything is fine as long as you remember to check whether function returned error. But what happen if you forgot to check that? It's actually a quite common problem.
Exceptions make the flow of a program much more natural.
Exceptions are hard to use in the correct context,especially in php. Personally i use exceptions when these 3 things happen:
Resource failure exception - You can throw an exception maybe when your program runs out of memory. for example in php when you run a script that exceeds 30 seconds executing. Though you can chanage that in .ini
Client code errors exceptions - For example when trying to connect to a database with the wrong credentials or unlinking a file not on server. Or when the database server is down and unresponsive, you can throw an exception.
Programmer error exception - These are errors generated due to your own coding problems.This can also be used when you are not sure of the results your code will give you. for example when dividing by 0.

Categories