how to "skip" php "exit" command? - php

I have following piece of code which I can't modify.
if ( empty($post->comment_status) ) {
do_action('comment_id_not_found', $comment_post_ID);
exit;
}
I can create function called during do_action processing (hooks in wordpress).
function my_function () {
//do something
}
add_action('comment_id_not_found', 'my_function');
Is it possible to skip the exit; command in the condition?
Thanks

One possible solution said to be ugly would be to throw exception in you function while having all code you can't modify run in try block. That is, if you can put it in try-catch.

exit is a statement, there is no way to get around it and no way to modify it. The only way to avoid it is to make sure that your code doesn't pass by it. (eg. if(FALSE) exit; won't exit but in this: do_something(); exit; do_something_else(); the function do_something_else() will not be called.)

Related

javascript exceptions vs php7 exceptions, how to pre-know throw statement's position in try block?

Consider the following javascript code debugging example:
try {
existentFunction1();
nonExistentFunction();
existentFunction1();
existentFunction1();
} catch (error) {
console.error(error); // expected output: ReferenceError: nonExistentFunction is not defined
}
The whole point of using try...catch is I don't pre-know which function inside try will throw error on runtime, that is when a user is interacting with the website in a way that executes the code inside the try
statement, I don't want the code to halt if one of the functions doesn't work as expected.
Now If I wanna do the same in php I need to put a throw statement (at least in php < 8, this post suggest we don't need throw).
Php code:
try {
function1();
function2();
// where to put throw? Before or after function3()?
function3();
function4();
}
catch(Exception $e) {
echo "Redirect the user to 404 page";
}
One way out of this, I think is to use try...catch for every suspected function, which defeats the purpose of using try catch, just use a switch or if-else for all functions. Or, if I already know which function could generate error, I don't need try-catch at all.
What am I missing in php exceptions? ...Coming from a javscript programming background.

Continue bubbling up inside a loop in PHP

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.

Proper way to 'exit' a script in PHP

I have a static method named ServerResponse that basically shows a message whether on success or fail. I just want to know the proper way to actually display the message and exit the script.
Should I implement my method like this:
public static function ServerResponse($e,$m){
print(json_encode([$e,$m]));
exit;
}
//Sample use:
if(this happens){
myclass::ServerResponse($x,$y);
}
or like this:
public static function ServerResponse($e,$m){
return json_encode([$e,$m]);
}
//Sample use:
if(this happens){
print(myclass::ServerResponse($x,$y));
exit;
}
Which one is proper and better... and why?
is there any difference between them? (on execution time).
"Don't be hard on me I am not an expert (just yet)..."
For better debugging, it's advised to always make a function or method return a value. So your 2nd sample should be chosen.
exit (or die) are commonly used when the program ends with an error, giving the ability to add an exit status (as a number or a string).
I suppose there will be no significant difference about the execution time.
I don't know if this is common practice but I only use exit to debug. If your script comes to the end of execution it will exit on it's own.
If you must exit, do it in the main script, not in a function.
functions should have one task and do that task. So the function ServerResponse should send a response and not kill the script.

Using a return keyword with no return value?

I have been noticing in some PHP design patterns, some authors who write code examples, have return inside the method but it doesn't specify return value .
It just says "return"
Can some one please explain me what is the purpose of doing that? Below is an example
Thank you!
function addListItem(ListItem $listItem){
if(in_array($listItem, $this->listitems, true)){
return;
}
$this->listitems[] = $listItem;
}
That's done for side-effects (IO, altering globals, or the arguments passed by reference, or an object property, like in your example -- $this->listitems[] = $listItem;), or to indicate it's impossible to yield a valid result.
return;
is equivalent to
return null;
The return statement will stop the function immediately after it has been called. Because we do not want any value to be returned like integers, string or booleans, we just stop it so the code will not continue.
This can also be compared to break in a for or while loop.
Well for starters, you may hit an if statement that makes the rest of the code in the method unnecessary.
For example:
if(user->log_in == "")
{
show_error_msg();
return;
}
The "technically more correct" way of writing such code is:
if( !in_array($listItem, $this->listitems, true)) {
$this->listitems[] = $listItem;
}
However, sometimes you may have more complex testing, and proceeding in this manner may result in a single if block spanning several lines with many &&s, or nested if statements that fall off the edge of your screen.
Therefore, it is common to see the pattern of your code, namely "check failure conditions and exit the current block if necessary". This means you can have as few or as many conditions as you want, each with their own failure conditions, and if the code manages to reach the end of it then you're good to go.
In some cases, error handling is useful. Something like:
try {
if( failure condition 1) throw new Exception("Error message 1");
if( failure condition 2) throw new Exception("Error message 2");
// ...
do something here;
}
catch(Exception $e) {
// report error here
}

Return (terminate) caller function from callee

I would like to create a forward-function that terminates the caller-function.
Currently I'm using "exit" in the callee-function to achieve this.
function caller (){
if($condition){
forward();
}
//code that is not executet if $condition is true
}
//current solution
function forward(){
//do something
exit;
}
I would like to omit the return-statement after calling the forward-function.
I guess there is no other way except throwing an exception?
Thanks for your help.
There are several ways:
1) Enclosing the code after if info else branch
2) As you mentioned, throwing an exception
3) or plainly doing:
function caller (){
if($condition){
forward();
return; // you return nothing (void, in PHP's case that would be NULL, I believe)
}
//code that is not executet if $condition is true
}
Throwing exceptions, using exit or some other nasty stuff is overkill no matter how you look at it (if all you want to do is conditional execution of some lines of code).
Solution 1
Use an else statement. This function will implicitly return NULL (in PHP, by default, ommiting the return statement when exiting a function, will return NULL to the caller).
function caller (){
if($condition){
forward();
}
else
{
//code that is not executet if $condition is true
}
}
Solution 2
The return statement will exit the current function.
function caller (){
if($condition){
forward();
return; //this function exits, and no other lines inside this function are executed
}
//code that is not executet if $condition is true
}
Don't use exit to terminate scripts, without passing and exit code. Exit is just like die, except instead of outputting to php://stdout (same thing as what echo does) it will return an exit code to the OS (exit is usefull only in CLI (command line) mode).
You can't terminate a "caller" function before the "called" function terminate itself.
There is a stack of calls that is allocated and return pointer issues.
I suppose that the best way to terminate a function itself is .... just terminate itself.
So
function caller (){
if($condition){
return 0;
}
//code that is not executet if $condition is true
}
I've only seen this answer in the comments, but not in any of the other answers.
To wrap up, let's consider two approaches and why they're not suitable for a forward functionality:
Use exceptions; exceptions should not be used for flow control, they're meant to handle exceptional events (when an operation has failed).
Use goto; this statement can only be used to jump within the same block of execution, which in this case would be inside the caller and the only jump target is at the end of the function.
Use exit(); this will terminate the script altogether and doesn't give any of the underlying code a chance to do anything else. It's typically used for fatal errors of some sort, or in rare cases whereby you set a few HTTP headers and then prevent any more output from being sent to the browser.
Technically speaking, a forward call should basically be used to express "say whatever he says"; and there's a perfect solution for that:
return forward();
It delivers the result of the forward() directly to the code that called the caller() while still respecting the stack execution order of your application.
Possibly, "goto" is the only solution:
function post_to_host($url, $data, $cook, $ref, &$resp_head, $type=1)
{$GLOBALS['POST_TO_HOST.TIME_START']=time();
...
stream_set_timeout($fp, 20);
fputs($fp, "Accept: */*\r\n"); if (check_timeout()) {goto timeout;}
fputs($fp, "Accept-Language: *\r\n"); if (check_timeout()) {goto timeout;}
fputs($fp, "Accept-Encoding: *\r\n"); if (check_timeout()) {goto timeout;}
while (!feof($fp))
{$line.=fgets($fp); if (check_timeout()) {goto timeout;}
}
return $line;
timeout:
{return 'POST EXCEPTION: Total timeout!';
}
}
function check_timeout()
{return time()-$GLOBALS['POST_TO_HOST.TIME_START']>60;
}

Categories