try catch statement in PHP where the file does not upload - php

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.

Related

Php selective exception handling

I have a problem where I want to catch all exception except descendants of my custom exception.
Maybe bad design, but here it is (Simplified and names changed, but the code is quite accurate):
function doStuff()
{
try {
// code
if (something) {
// manually throw an exception
throw StuffError("Something is bad.");
}
// a third-party code, can throw exceptions
LibraryClass::arcaneMagic();
} catch (Exception $e) {
throw new StuffError("Error occured while doing stuff: "
. $e->getMessage());
}
}
/** My custom exception */
class StuffError extends Exception
{
function __construct($msg) {
parent::__construct('StuffError: ' . $msg);
}
}
However, the issue here is that I don't want the try-catch to intercept the manually throws StuffError. Or, seamlessly rethrow it or something.
As it is now, I'd get:
StuffError: Error occured while doing stuff: StuffError: Something is bad.
I want just:
StuffError: Something is bad.
How would I do it?
You can have multiple catch clauses, and the first one that matches will be the one that runs. So you could have something like this:
try {
do_some_stuff();
}
catch (StuffError $e) {
throw $e;
}
catch (Exception $e) {
throw new StuffError(Error occurred while doing stuff: " . $e->getMessage());
}
But you might want to rethink wrapping stuff like this. It obscures the real cause of the error. For one thing, you lose the stack trace. But it also complicates error handling, since now someone can't differentiate exception types the way you're trying to do, short of trying to parse the exception message (which is rather an anti-pattern in itself).
I might be misinterpreting you, but I think this is what you're looking for:
...
} catch (Exception $e) {
if (get_class($e) == 'StuffError' || is_subclass_of($e, 'StuffError')) {
throw $e;
} else {
throw new StuffError("Error occured while doing stuff: "
. $e->getMessage());
}
}
...
Replace your catch statement with the code above. It checks to see if the exception is a StuffError or a child class of StuffError. I'm still very confused at why you would need to throw a StuffError exception after you catch, but maybe that's just some weirdness coming from translating/cleaning your code.

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

Can I use try-catch-finally like this?

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.

Too many try/catch block for PDO

In the controllers class files, most of the method functions include try/catch block something like this:
try
{
$stmt = $this->prepare($sql);
$stmt->execute($params);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
//foreach() or so on...
}
catch (Exception $e)
{
//bunch of code...
//save error into database, etc.
//error into json and pass to view file
}
There are a lot of code in the catch block, is there a way to reduce it. Is possible to add "throw exception" in the catch block?
Yes, it is. Try it by yourself. You can always throw a new Exception in a catch block or rethrow the same exception.
try
{
// ...
}
catch (Exception $e)
{
// do whatever you want
throw new Your_Exception($e->getMessage());
// or
throw $e;
}
I don't know what "bunch of code" is. I'm not sure I believe you. If you have that much going on in a catch block you're doing something wrong.
I'd put this kind of code into an aspect if you have AOP available to you.
"Error into database" might throw its own exception. What happens to that?
The only step that I see here that's necessary is routing to the error view.
What does rethrowing the exception do? It's just passing the buck somewhere else. If all these steps don't need to be done, and all you're doing to rethrowing, then don't catch it at all. Let the exception bubble up to where it's truly handled.
You shouldn't be catching Exception. That's much too general. Catch each specific type of Exception with multiple catch statements on your try block:
try {
} catch(PDOException $err) {
} catch(DomainException $err) {
}

Return PHP error constant (such as E_USER_ERROR) from function, or use trigger_error?

Which would you recommend?
Return an error code, such as E_USER_ERROR from a function, and determine proper message higher up:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//This?
return E_USER_ERROR;
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
Execute trigger_error() from the function, with a specific error message:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//Or this?
trigger_error('$_SERVER[\'SCRIPT_FILENAME\'] is not set.', E_USER_ERROR);
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
I am not sure if I will regret having put a bunch of error messages in my functions further down the line, since I would like to use them for other projects.
Or, would you recommend something totally different?
Do not mix the matters.
Error notification and error handling are different tasks.
You have to use both methods simultaneously.
If you think that $_SERVER['SCRIPT_FILENAME'] availability is worth an error message, you can use trigger error. However PHP itself will throw a notice if you won't check it.
If you want to handle this error, just check this function's return value.
But I would not create a special function for this task.
So,
if (!$filename = basename($_SERVER['SCRIPT_FILENAME']) {
// do whatever you want to handle this error.
}
would be enough
Exceptions could be useful to handle errors, to know if we had any errors occurred.
A simple example:
try {
$filename = basename($_SERVER['SCRIPT_FILENAME'])
if (!$filename) throw new Exception("no filename");
$data = get_some_data_from_db() or throw new Exception("no data");
$template = new Template();
//Exception could be thrown inside of Template class as well.
}
catch (Exception $e) {
//if we had any errors
show_error_page();
}
$template->show();
3.Use exceptions.
If this is the route you are going, I'd rather recommend throwing Exceptions rather then returing an E_ERROR (E_USER_ERROR should be used), as this is just an integer, and possibly a totally valid return for your function.
Advantages:
- Throwing of an Exception cannot be interpreted as anything else then an error by mistake.
- You keep the possibility to add a descriptive error message, even though you don't handle the error at that point/
- You keep a backtrace in your Exception.
- You can catch specific exceptions at specific points, making the decision where in your project a specific type of error should be handled a lot easier.
If not using exceptions which you should be, use trigger_error().
If it is an error you'd like to deal with, try returning FALSE like a lot of the in built functions do.
If you do use exceptions, catch them like this
try {
whatever()
} catch (Exception $e) {
// handle however
}

Categories