I want to return multiple nested functions in PHP. It's possible to break out of multiple loops by adding a number after "break". Eg.
while(1)
while(1)
while(1)
break 3;
Can I do a circuit break while calling a sequence of functions?
Not that I know of, it's also not very healthy of a design, as the parent and grandparent functions in question will never know of the break. You should throw an exception and catch it on the parent, which in turn will throw an exception and catch it on the grandparent etc.
To "break" out of functions, you can use the return.
function somefunction()
{
return;
echo 'This will never get displayed';
}
Another solution would be to add a condition to each while.
while(1 && $isTrue)
while(1 && $isTrue)
while(1 && $isTrue)
$isTrue = false;
break;
Although I don't think this is a very clean approach.
As the manual states break is for loop only.
What I do in such cases is that have an exception return value(or object) and do value check on return value at every function return point to make sure that the situation is propagated or handled appropriately, be careful while doing recursions though, you might completely fold up the tree by mistake....btw if it is a simple exit on error kind of situation you can also use exceptions.
It's possible to return a special result from child functions that indicates a specific condition has been met. WordPress uses WP_Error and is_wp_error() for this sort of operation. Any number of nested functions can check to see if a called function returned an error state, and opt to pass that error up the chain rather than continue with processing.
Example:
function outer() {
$result = inner();
// pass failure back to parent
if( is_wp_error($result) ) {
return $result;
}
// other processing
return $final_result;
}
function inner() {
if( some_condition() ) {
// generate an error
return new WP_Error( 'code', 'message' );
}
return $other_result;
}
$result = outer();
// did we get an error?
if( is_wp_error($result) ) {
echo 'Something went wrong.';
} else {
echo $result;
}
Yes, you can very simply construct a "body-less" while() or if() block. Typically, you will see PSR-12 compliant PHP code using {} to bookend the body of the loop/condition block, but the body is not required. Writing a semicolon at the end of the line will be sufficient and your IDE will not complain about bad syntax.
Returning a truthy value from each function will be an adequate indicator that the following function is authorised for execution.
This will provide the "short circuit" functionality that is desired without creating nested control structures or passing variables into different scopes.
I'll demonstrate with a battery of generic functions:
function echo1T() {
echo "1";
return true;
}
function echo2T() {
echo "2";
return true;
}
function echo3T() {
echo "3";
return true;
}
function echo1F() {
echo "1";
return false;
}
function echo2F() {
echo "2";
return false;
}
function echo3F() {
echo "3";
return false;
}
Code: (Demo with more scenarios)
while (echo1T() && echo2F() && echo3T()); // outputs: 12
if (echo1T() && echo2F() && echo3T()); // outputs: 12
$return = echo1T() && echo2F() && echo3T(); // outputs: 12
var_export($return); // outputs false
Related
Is there a way to have PHP discontinue execution of a class if my error variable (not a PHP error but a error set when input is invalid) is ever set without constantly checking the error variable? like a passive listener? My script has many places a error could occur. Something like this:
if(empty($this->error)) $this->error= function1();
if(empty($this->error)) $this->error= function2();
if(empty($this->error)) $this->error= function3();
$this->error is always returned a null value unless a error occurs. if it is ever not null I want exit the rest of the function with out having to put if(empty($this->error)) in front of everything.
Edit: farther explanation:
I suppose I want something that automatically checks if $this->error is empty after every line of code, without me telling it to, then exits the function if it's not empty, like a break in a loop.
the suggested posts do not solve my problem as they still require the condition be manually checked. I want something like this:
stays_empty($this->error)
{
$this->error= function1();
//PHP checks if $this->error is still empty. Continue if it is, break if it's not.
$this->error= function2();
//PHP checks if $this->error is still empty. Continue if it is, break if it's not.
$this->error= function3();
//PHP checks if $this->error is still empty. Continue if it is, break if it's not.
}
When doing repetitive actions, you should consider using loops instead of repeating code many times.
Many may not know this, but you can actually use variables a function names too as shown in this example.
<?php
class Whatever
{
function __construct() {
// Names of the functions we wish to run
$functionNameList = ['function1', 'function2', 'function3'];
// Looping our function names
foreach ($functionNameList as $key => $functionName) {
// Inserting variable as function name
$this->error = $this->$functionName();
if ($this->error) {
echo 'Error found ';
break; // This would break out of the foreach loop [OR]
return; // This will break out of the function
}
}
}
public function function1() {
echo 1;
return '';
}
public function function2() {
echo 2;
return 'error';
}
public function function3() {
echo 3;
return '';
}
}
$x = new Whatever();
You could also use exceptions as mentioned in other answers, but I'm answering your question in a fashion suitable for any situation with lots of repetition.
Edit: Short Version
$functionNameList = ['function1', 'function2', 'function3'];
foreach ($functionNameList as $key => $functionName) {
$this->error = $this->$functionName();
if ($this->error) {
break;
}
}
Edit: Super Short Version (Not as clear)
$functionNameList = ['function1', 'function2', 'function3'];
foreach ($functionNameList as $key => $functionName) {
if ($this->error = $this->$functionName()) {
break;
}
}
I have this code in a function:
if ($route !== null) { // a route was found
$route->dispatch();
} else {
// show 404 page
$this->showErrorPage(404);
}
Now PHPmd gives an error:
The method run uses an else expression. Else is never necessary and
you can simplify the code to work without else.
Now I'm wondering if it really would be better code to avoid the else and just add a return statement to the if part?
PHPMD is expecting you to use an early return statement to avoid the else block. Something like the following.
function foo($access)
{
if ($access) {
return true;
}
return false;
}
You can suppress this warning by adding the following to your class doc block.
/**
* #SuppressWarnings(PHPMD.ElseExpression)
*/
You usually can rewrite the expression to use just an if and it does subjectively make the code more readable.
For example, this code will behave in the same way if showErrorPage breaks the execution of the code.
if ($route == null) {
$this->showErrorPage(404);
}
$route->dispatch();
If the content of your if statement does not break the execution, you could add a return
if ($route == null) {
$this->showErrorPage(404);
return;
}
$route->dispatch();
If you where inside a loop, you could skip that iteration using continue
foreach ($things as $thing ) {
if ($thing == null) {
//do stuff and skip loop iteration
continue;
}
//Things written from this point on act as "else"
}
I wouldn't worry about what PHPmd says , atleast in this case.
They probably meant for you to use the conditional operator because (in their opinion) its 'cleaner'.
$route !== null ? $route->dispatch() : $this->showErrorPage(404) ;
Remove the else block by ending the 404 producing branch:
if ($route === null) {
// show 404 page
$this->showErrorPage(404);
return;
}
// a route was found
$route->dispatch();
This answer is coming late, but another method you can get around that is by using else if. Because sometimes you cannot just return if some logic should follow.
Having your example
if ($route !== null) { // a route was found
$route->dispatch();
}
else if ($route === null) {
$this->showErrorPage(404);
}
$route->doSomething();
What are the best usages of functions that end with "return;" and what are the advantages of writing a function that ends this way?
Example:
function MyFunction() {
// (do something)
return;
}
Thank you
You shouldn't, I would always use return null; so that it is an explicit declaration of what is returned (even if it is null). I'm sure this is also in one of the PSR specs as well, but I don't know them well. To confirm that return; === return null;:
function test() {
return;
}
var_dump(test());
// NULL
As to when you would want to return null;..any function that returns something, should always return something. So maybe if you have a function that gathers and returns a value from a DB, and an error occurs:
public function retrieveData()
{
$data = DB::retrieve();
if(!$data) {
return null;
}
return $data;
}
However, a lot of functions that may have errors just return true/false on success or failure so you won't necessarily use this often.
My main point to drive home: if you don't want/need to return anything, don't return anything.
A return; says only "thats the end". Mostly useful in following examples:
function test($string) {
if(empty($string)) {
return; // If the variable is empty, then stop to work!
}
echo $string;
}
A simple example is that you can write a PHP function that spits out formatted HTML:
function printHeader($value)
{
echo "<h1>$value</h1>";
return;
}
However, since you are not returning anything, the return statement is unnecessary and can be left out.
If you are talking about a empty return;, I can think of one example, if you have code that should be executed under a condition, and more code that should be executed if that condition is not met.
function MyFunction() {
if(a < 1) {
// (do something)
return;
}
// If a >= 0 it executes the code above and the code below
// Do something else
}
This is more or less a readability, maintainability and/or best practice type question.
I wanted to get the SO opinion on something. Is it bad practice to return from multiple points in a function? For example.
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== FALSE) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
} else {
return FALSE;
} else {
// returning false because $a->value isn't set
return FALSE;
}
}
?>
or should it be something like:
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== false) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
}
}
return FALSE
}
?>
As a matter of practice, I always try to return from ONE point in any function, which is usually the final point. I store it in a variable say $retVal and return it in the end of the function.It makes the code look more sane to me.
Having said that, there are circumstances where say, in your function as the first line you check if a var is null and if yes you are returning. In this case, there is no point in holdin on to that variable, then adding additional checks to skip all the function code to return that in the end.
So...in conclusion, both ways works. It always depends on what the situation is and what you are more comfortable with.
I have checked a few other questions but they don't really give me the answer I expect..
My code is a like this..
private function handle()
{
if()
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition))
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
if(!condition)
{
code
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
In my opinion it is readable but messy, sadly I haven't found really a way of making it look 'pretty'. Any ideas?
EDIT: Each return is different.
EDIT2: Gave an answer of my own, thanks everybody!
Conditions can be merged by a && operator..It works form left to right, which means, as soon as the any one starting from left fails, it stops evaluating the condition..
if($a) {
if($b) {
}
}
can be replaced by
if($a && $b) {
}
Use a variable check, or combine the conditions into fewer IF statements.
Variable check like so:
$execute = TRUE;
// Opposite of what you want, e.g. if you want $a only to be TRUE, do $a !== TRUE
if (condition) {
$execute = FALSE;
}
...
// If all the conditions were met, then everything is OK
if($execute === TRUE) {
// code
}else {
// return
}
Edit:
Variable check can be preferably to combining IF statements if you want more control on what returns, e.g. something specific happens if a certain condition fails, which combining conditions can not always allow for.
Like already posted use
if(condition1&&condition2){}
or if this will not work, you can also use function which stops as soon as a condition is true
function some(){
if(!conditon 1){return 0;}
if(condition 2) {return 1;}
}
this provides more power as second if works only if first doesn't satisfy.
You must choose based on your requirements. Sometimes though nested loops are unavoidable.
I thought it out and have found a nice way of doing it, basically I'll make a method for each basic condition, and I'll call them in an if statement with the bitwise AND operator (&), which don't short-circuit.
/**
* nonsql_condition - It means it doesn't check with the database
*
* sql_condition - It means it does check with the database.
*/
if(!$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition() & !$this->nonsql_condition())
{
if(!$this->sql_condition())
{
return error;
}
if(!$this->sql_condition())
{
return error;
}
code;
}
This allows me to use fewer lines of code in my method, plus also not doing unnecessary queries to my database.