I adapted a web script I wrote to fit my needs for some data I need to retrieve from a server. I run this script from a terminal, so error messages are useful information.
The main part of the code is a loop inside a loop, and in that loop I call a function. In this function there's a call to a database. If there is a problem with connecting to the database, I can catch that error with a simple try {} catch(){}
, but how should I structure my code so that I can just skip this iteration and move to the next item in the loop? In other words, do a continue
only from within a function.
Below is how I would do it, but I am not sure this is the correct way.
foreach ($flavours as $icecream) {
foreach ($sauces as $sauce) {
$amount = dessertServings($icecream, $sauce);
if ($amount != null) {
// Some other functions like orderDessert, makePricingList and so on
fwrite(STDOUT, "$amount servings of $icecream with $sauce remaining!\n");
}
}
}
dessertServings($icecream, $sauce) {
try {
$dbConnection = new Connection("user", "password", "db$icecream$sauce");
$amountOfServings = $dbConnection->query($icecream, $sauce);
return $amountOfServings;
}
// E.g database connection could not be made
catch(Exception $e) {
fwrite(STDERR, $e->getMessage() . "\n");
return;
}
}
Is there a better way to do this?
To make things harder, what if the function doesn't actually return anything and thus isn't assigning a value to a variable? How should you deal with that?
foreach ($flavours as $icecream) {
foreach ($sauces as $sauce) {
prepareDessert($icecream, $sauce);
// Other functions, most importantly: eatDessert($dessert)
}
}
prepareDessert($icecream, $sauce) {
try {
$dbConnection = new Connection("user", "password", "db$icecream$sauce");
$dbConnection->query($icecream, $sauce)->do("prepare");
}
// E.g database connection could not be made
catch(Exception $e) {
fwrite(STDERR, $e->getMessage() . "\n");
}
}
In such a case, how do I make sure that when the try
fails, the block in the loop never reaches the other functions, we can't eat an ice cream that wasn't prepared in the first place!
Would I use an empty variable that simply returns true on success and false and fail, and execute the following code in the main block only on true? Or is there a better convention for this in PHP?
how should I structure my code so that I can just skip this iteration and move to the next item in the loop
The first rule of exception handling: do not do exception handling. Allow it to bubble up and catch it when you need it (in your case, in your loop).
You can also re-throw an exception in your catch, if you want to do some processing within the function (like print to STDERR), but let it bubble up!
The other more traditional method is to have your function return some kind of error code - the most basic being "true" on success, "false" or "null" on failure like in your first example. I don't see anything wrong with that.
To make things harder, what if the function doesn't actually return anything and thus isn't assigning a value to a variable? How should you deal with that?
Throw exceptions, that's their job!
how do I make sure that when the try fails, the block in the loop never reaches the other functions
Don't try/catch within the function or re-throw an exception from within your "catch".
Would I use an empty variable that simply returns true on success and false and fail, and execute the following code in the main block only on true? Or is there a better convention for this in PHP?
Yes there is a better convention : throw exceptions.