Can I use try-catch-finally like this? - php

I'm using try-catch for years, but I never learned how and when to use finally, because I never understood the point of finally (I've read bad books)?
I want to ask you about use of finally in my case.
My code example should explain everything:
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
$s = $c->get_file_content($path);
}
Is this correct use of finally?
More precise question:
Shall I use finally (in future PHP versions or other languages) for handling "create something if it not exists" operations?

Finally will always be executed, so in this case, it is not its intended purpose, since normal execution would reopen the file a second time. What you intend to do would be achieved in the same (cleaner) way if you do
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
$s = $c->get_file_content($path);
}
Then the manual says:
For the benefit of someone anyone who hasn't come across finally blocks before, the key difference between them and normal code following a try/catch block is that they will be executed even the try/catch block would return control to the calling function.
It might do this if:
code if your try block contains an exception type that you don't catch
you throw another exception in your catch block
your try or catch block calls return
Finally would then be useful in this kind of scenario:
function my_get_file_content($path)
{
try
{
return $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
return $c->get_file_content($path);
}
finally
{
$c->close_file_handler();
}
}
=> if you need to make sure you close your file handler in this case, or some resource in general.

finally wasn't introduced into PHP until version 5.5 which has not been released yet so that why you haven't seen any examples with it yet. So unless you're running and alpha version of PHP 5.5 you can't use finally yet.
From the manual (exceptions)
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.
Example from the manual of using finally
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "Second finally.\n";
}
// Continue execution
echo 'Hello World';
?>

Finally means what do you want to DO Finally.
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
//Create a pdf with my file
//or, Rename my file
//or, store my file into Database
}
No matter what happens(regardless of whether an exception has been thrown) inside try or catch, 'Finally code' will execute.
So, no point of using same code over 'try' and 'finally'.
Does this simply answer your question?

I just want to appoint that if an Exception occurs in the try block, the exception will be correctly raised even if the finally block is present.
The usefulness of the finally block is for clean and free resources.
I think it's best use is when, for example, you upload a file but then an error happens:
$tmp_name = null;
try {
$tmp_name = tempnam(UPLOAD_DIR, 'prefix');
move_uploaded_file($file['tmp_name'], $tmp_name);
ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
if($tmp_name)
unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}
As you can see, in this way no matter what happen, the temp file will be correctly deleted.
If we would emulate the finally clause in older version of PHP, we should write something like this:
// start finally
catch(Exception $ex) {
}
if($tmp_name)
unlink($tmp_name);
if( isset($ex) )
throw $ex;
// end finally
Note that the exception has been re-thrown in case the catch block caught something. It isn't clear as the finally version, but works the same.

Related

php code logic by version

I want a solution something like: Imagine I have try catch block, it works in any php 5.?.? version but with finally block not in any. my code must be like this:
try {
// some logic
} catch (Exception $ex) {
// some logic
} finally {
// other logic
}
but, how can I make so that finally block worked only if php version supports it else ignore? For example:
try {
// some logic
} catch (Exception $ex) {
// some logic
}
#if version=5.?.?
finally {
// other logic
}
#endif
Is there any solution?
You can get php version by phpversion method. The only option you have is to write an if statement to check it; if it supports write the whole try-catch-finally block. If it does not, write only try-catch. You can use inline functions to prevent duplicate code. I have no idea why somebody needs this, but for example;
function fncTry(){...}
function fncCatch($exception){...}
function fncFinally(){...}
if($phpVersion == '5.5'){
try { fncTry(); }
catch(Exception $ex) { fncCatch($ex); }
finally { fncFinally(); }
}else{
try { fncTry(); }
catch(Exception $ex) { fncCatch($ex); }
fncFinally();
}
Yes.
phpversion() will return a string of the php version. (Example: "5.6.14")
You can use that to set up your conditional statement.
i am sorry i'm confused :)
check this
and you could check about phpversion before you make the try catch
if (php version == 5.5 or greater)
you make it with finally
else you make it without finally

Formatting error log using PDO

I would like the error log to show each error on a new line beginning with a time stamp.
Currently the errors just show up in a connected chunk.
catch(PDOException $e) {
file_put_contents('logs/insert_errors.txt', $e->getMessage(), FILE_APPEND);
}
I'm sure this is fairly simple. Just my first time working with PDO and not sure how to accomplish this.
Preamble: As #Phil mentioned this has nothing to do with PDO.
There are two parts to your question:
a) it is all in one connected line
The reason is quite obvious, you are not adding a new line character at the end. What that character(s) is(are) depend on your OS, but PHP solves that for you with the PHP_EOL constant that you can just append to the end of your string.
b) you want a timestamp at the beginning of each line
Again, the issue is because you didn't put it there. Just adding the output of date('r') before printing out the message should be enough.
The real solution: a real logger
You may want to look at using a complete logging solution for your code. Someting like log4php, for example.
Homebrew solution
Alternatively, if that is too much, you could build your own logger. A good small example one can be found in the comments of the documentation of PHP's error_log function that I adapted for your needs:
Class Log {
const ERROR_DIR = '/home/site/error_log/db_errors.log';
// Log PDO errors
public function error($msg) {
$date = date('r');
$log = sprintf('%s: %s%s', $date, %msg, PHP_EOL);
error_log($log, 3, self::ERROR_DIR);
}
// shortcut for PDO exceptions
public function exception($e) {
$this->error($e->getMessage())
}
}
try {
$log = new log();
$log->error($msg); //use for general messages
} except (Exception $e)
$log->exception($e); //use for exceptions
}
Simply format the string to be inserted, eg
catch (PDOException $e) {
$error = sprintf('%s: %s%s', date('c'), $e->getMessage(), PHP_EOL);
file_put_contents('logs/insert_errors.txt', $error, FILE_APPEND);
// don't forget to re-throw the exception otherwise your program will
// continue execution
throw $e;
}

What's the `finally` keyword for in PHP?

Consider these two examples
<?php
function throw_exception() {
// Arbitrary code here
throw new Exception('Hello, Joe!');
}
function some_code() {
// Arbitrary code here
}
try {
throw_exception();
} catch (Exception $e) {
echo $e->getMessage();
}
some_code();
// More arbitrary code
?>
and
<?php
function throw_exception() {
// Arbitrary code here
throw new Exception('Hello, Joe!');
}
function some_code() {
// Arbitrary code here
}
try {
throw_exception();
} catch (Exception $e) {
echo $e->getMessage();
} finally {
some_code();
}
// More arbitrary code
?>
What's the difference? Is there a situation where the first example wouldn't execute some_code(), but the second would? Am I missing the point entirely?
If you catch Exception (any exception) the two code samples are equivalent. But if you only handle some specific exception type in your class block and another kind of exception occurs, then some_code(); will only be executed if you have a finally block.
try {
throw_exception();
} catch (ExceptionTypeA $e) {
echo $e->getMessage();
}
some_code(); // Will not execute if throw_exception throws an ExceptionTypeB
but:
try {
throw_exception();
} catch (ExceptionTypeA $e) {
echo $e->getMessage();
} finally {
some_code(); // Will be execute even if throw_exception throws an ExceptionTypeB
}
fianlly block is used when you want a piece of code to execute regardless of whether an exception occurred or not...
Check out Example 2 on this page :
PHP manual
Finally will trigger even if no exception were caught.
Try this code to see why:
<?php
class Exep1 extends Exception {}
class Exep2 extends Exception {}
try {
echo 'try ';
throw new Exep1();
} catch ( Exep2 $e)
{
echo ' catch ';
} finally {
echo ' finally ';
}
echo 'aftermath';
?>
the output will be
try finally
Fatal error: Uncaught exception 'Exep1' in /tmp/execpad-70360fffa35e/source-70360fffa35e:7
Stack trace:
#0 {main}
thrown in /tmp/execpad-70360fffa35e/source-70360fffa35e on line 7
here is fiddle for you. https://eval.in/933947
From the PHP manual:
In PHP 5.5 and later, a finally block may also be specified after or instead of 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.
See this example in the manual, to see how it works.
http://www.youtube.com/watch?v=EWj60p8esD0
Watch from: 12:30 onwards
Watch this video.
The language is JAVA though.
But i think it illustrates Exceptions and the use of finally keyword very well.

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

try catch statement in PHP where the file does not upload

I understand what try-catch statements do, but from reading the documentation on php.net, I would not be able to implement one into my own code. I need a real example to help me understand.
How can I turn this example into a try-catch statement, if the upload was not successful?
$move = move_uploaded_file($_FILES['file']['tmp_name'], $_SERVER['DOCUMENT_ROOT'].'/uploads/'.$_FILES['file']['name']);
if (!$move) {
die ('File didn\'t upload');
} else {
//opens the uploaded file for extraction
echo 'Upload Complete!';
}
This may not be a good example to work with, but any help would be appreciated.
You could do it like this.
try {
//throw exception if can't move the file
if (!move_uploaded_file( ... )) {
throw new Exception('Could not move file');
}
//do some more things with the file which may also throw an exception
//...
//ok if got here
echo "Upload Complete!";
} catch (Exception $e) {
die ('File did not upload: ' . $e->getMessage());
}
It is a bit pointless for the above example, but you should get the idea. Note that you can throw the exception(s) from anywhere (e.g. within a function/method that you call from withing the try{}) and they will propagate upwards.
Well, if you want to use exceptions, you could do something like:
function handleUpload() {
$move = move_uploaded_file($_FILES['file']['tmp_name'], $_SERVER['DOCUMENT_ROOT']."/uploads/".$_FILES['file']['name']);
if (!$move) {
throw new Exception('File Didnt Upload');
}
}
try {
handleUpload();
echo "File Uploaded Successfully";
} catch(Exception $ex) {
die($ex->getMessage);
}
I know this may seem like bloat - but you can call the method from anywhere in the call stack, and catch the exception at any point.
try-catch statements are used to handle exceptions. I don't believe that the function move_uploaded_files can throw and exception, as such I think that you code is written is correct. After the call, you look at the return code. If it's false, you end processing, otherwise you are report success.
According to a similar post in PHPbug, only OO code (Object-Oriented code) throws exceptions. That would mean that functions such as move_uploaded_file won't throw their own exceptions, but some other code will.

Categories