Start function over, depending on results of IF statement - php

If I have a function that is inside of a Class, and I am returned with "invalid" how can I start back up at the top function?
function test(){
//curl here
//other stuff here
if(strpos($data, 'invalid')){
print "invalid";
//discard and remove
continue ;
}
}
but I get the following error
Fatal error: Cannot break/continue 1 level in
If I am hit with "invalid" I would like to start test() back over..

You probably want to use a recursive function here:
function test(){
//curl here
//other stuff here
if(strpos($data, 'invalid')){
print "invalid";
//discard and remove
return test() ; // restart process
}
}
Alternatively, this may be a (very rare) good use of the goto operator:
function test(){
start:
//curl here
//other stuff here
if(strpos($data, 'invalid')){
print "invalid";
//discard and remove
goto start;
}
}
Note that this will only work in PHP >=5.3.

I'd make use of exceptions, and let the calling scope control repeat invocations of test(). test() performs one job; it shouldn't control when it's asked to perform that job.
(Recursive approaches given in other examples don't really fit the use case [and make me nervous, thanks to languages where recursing too many times makes you run out of stack space eventually; certainly you're filling up your stack for no reason], and though goto will work fine it still gives the function itself too much power.)
function test()
{
//curl here
//other stuff here
if (strpos($data, 'invalid'))
throw new Exception("Data is invalid");
}
function callingFunction()
{
while (true) {
try {
test();
break; // only reached if test() didn't throw
}
catch(Exception $e) {} // if we fall into this, the loop repeats
}
}
You could still apply goto quite cleanly with this approach:
function test()
{
//curl here
//other stuff here
if (strpos($data, 'invalid'))
throw new Exception("Data is invalid");
}
function callingFunction()
{
startTest:
try {
test();
}
catch(Exception $e) {
goto startTest;
}
}

Remove continue; and instead add test();. It's called recursive functions (calling itself).

There are a few ways you can do it, the way my teacher normally suggests is to actually call the function again.
function test(){
//curl here
//other stuff here
if(strpos($data, 'invalid')){
print "invalid";
//discard and remove continue ;
test();
return;
}
}
My answer might not be the best, hope this helps.

Assuming you change the parameters beforehand, you can recursively call the function again with new parameters. Just make sure there will be an edge case where the function will stop recursing. As for that, I'd need to see the real code to tell you.
function test($data){
//curl here
//other stuff here
if(strpos($data, 'invalid')){
print "invalid";
//discard and remove
test($NEW_DATA);
}
}

If you want to break out of the function you're currently in, you should use 'return' instead of 'continue'.
Or if you would like to start the processing over, you should put your logic into a loop.

Related

Force return statement on caller function

I am just curious if it's possible to force parent method to return a value from within method called in that parent method? Let's say I have:
public function myApiEndpoint()
{
// I DO NOT want to to have return statement here
$this->validOrUnprocessable();
// some other code
//return value
return $someValue;
}
public function validOrUnprocessable()
{
if ($condition) {
... here goes the code that forces return statement on myApiEndpoint function without putting the word `return` in front of this call...
}
}
So in other words validOrUnprocessable method, when it needs to do so forces or tricks PHP into thinking that myApiEndpoint returns the value. I do not want to use return statement when validOrUnprocessable is called or any if conditions.
I do know other ways of doing what I want to do but I wanted to know if something like that is possible. I am not interested in any workarounds as I know very well how to implement what I need to achieve in many other ways. I just need to know if this what I described is possible to do exactly how I described it.
I did try to get there with reflections and other scope related things but so far no luck. Any ideas?
Just to add. I am doing this because I want to check how far I can push it. I am building a tool for myself and I want it to be as convenient and easy to use as possible.
If it's not possible I have another idea but that's a bit out of the scope of this post.
You should throw an exception.
public function validOrUnprocessable()
{
if ($condition) {
throw Exception('foo bar');
}
}
The code calling this method should be ready to catch an exception:
public function myApiEndpoint()
{
try {
// I DO NOT want to to have return statement here
$this->validOrUnprocessable();
// some other code
//this code will never be called because of exception thrown in validOrUnprocessable
return value;
} catch (Exception $e) {
//do something else
return -1; //you can return another value as example.
}
return $someValue;
}

use goto inside function php

Is there a way to define global label (something like variables) for PHP goto, in order to use it inside function declaration. I want to do the following:
function myFunction() {
if (condition) {
goto someLine;
}
}
someLine:
// ....
myFunction();
when I use this code it says
PHP Fatal error: 'goto' to undefined label "someLine"
I know that it is not recommended to use goto statement. But I need it in my case. I know that perhaps always there are alternatives of goto, just in my case it would make the code a little easier and understandable
You cannot goto outside of a function I believe: http://php.net/manual/en/control-structures.goto.php
Direct Quote:
This is not a full unrestricted goto. The target label must be within the same file and context, meaning that you cannot jump out of a function or method, nor can you jump into one.
This might have to do with the fact that php is parsed and jumping out of a function will cause a memory leak or something because it was never properly closed.
Also as everyone else said above, really you don't need a goto. You can just return different values from the function and have a condition for each. Goto is just super bad practice for modern coding (acceptable if you are using basic).
Example:
function foo(a) {
if (a==1) {
return 1;
} elseif (a==3) {
return 2;
} else {
return 3;
}
}
switch (foo(4)) { //easily replaceable with elseif chain
case 1: echo 'Foo was 1'; break; //These can be functions to other parts of the code
case 2: echo 'Foo was 3'; break;
case 3: echo 'Foo was not 1 or 3';
}
There's no way to jump in or out of a function. But since you state that you need it, here's an alternative route.
function myFunction() {
if (condition) {
return true;
}
return false;
}
someLine:
// ....
$func = myFunction();
if($func == true) goto someLine;
As previously stated you can't. As for "I need it", I highly doubt this. Whatever code you have at someLine: can easily be made into a function that you can call from the other if needed.
yeah there's a way as long as that function is declared on the same php file or is included if its on another script,
the best way to jump on to someline is to return that goto code of yours dude so that if function is called a return value is received.. hope this helps
function foo($b="30")
{
$a=30;
if($a==intval($b))
return "someline:goto
someline";
}
try{
eval(foo());
}
catch(IOException $err)
{
exit($err);
}
/*someline is somewhere here
for example */

Any way to exit outer function from within inner function?

Within PHP, if I have one function that calls another function; is there any way to get the called function to exit out of the caller function without killing the entire script?
For instance, let's say I have some code something like:
<?php
function funcA() {
funcB();
echo 'Hello, we finished funcB';
}
function funcB() {
echo 'This is funcB';
}
?>
<p>This is some text. After this text, I'm going to call funcA.</p>
<p><?php funcA(); ?></p>
<p>This is more text after funcA ran.</p>
Unfortunately, if I find something inside of funcB that makes me want to stop funcA from finishing, I seem to have to exit the entire PHP script. Is there any way around this?
I understand that I could write something into funcA() to check for a result from funcB(), but, in my case, I have no control over the contents of funcA(); I only have control over the contents of funcB().
To make this example a little more concrete; in this particular instance, I am working with WordPress. I am hooking into the get_template_part() function, and trying to stop WordPress from actually requiring/including the file through the locate_template() function that's called after my hook is executed.
Does anyone have any advice?
Throw an exception in funcB that is not handled in funcA
<?php
function funcA() {
try
{
funcB();
echo 'Hello, we finished funcB';
}
catch (Exception $e)
{
//Do something if funcB causes an error, or just swallow the exception
}
}
function funcB() {
echo 'This is funcB';
//if you want to leave funcB and stop funcA doing anything else, just
//do something like:
throw new Exception('Bang!');
}
?>
The only way I see is using exceptions:
function funcA() {
funcB();
echo 'Hello, we finished funcB';
}
function funcB() {
throw new Exception;
echo 'This is funcB';
}
?>
<p>This is some text. After this text, I'm going to call funcA.</p>
<p><?php try { funcA(); } catch (Exception $e) {} ?></p>
<p>This is more text after funcA ran.</p>
Ugly, but it works in PHP5.
Maybe...
It's not an solution, but you could hook another function that gets called when exit() is requested "register_shutdown_function('shutdown');". And to somehow have this get things continue again or complete to your satifaction.
<?php
function shutdown()
{
// This is our shutdown function, in
// here we can do any last operations
// before the script is complete.
echo 'Script executed with success', PHP_EOL;
}
register_shutdown_function('shutdown');
?>

PHP Always run function

I am trying to get some errors returned in JSON format. So, I made a class level var:
public $errors = Array();
So, lower down in the script, different functions might return an error, and add their error to the $errors array. But, I have to use return; in some places to stop the script after an error occurs.
So, when I do that, how can I still run my last error function that will return all the gathered errors? How can I get around the issue of having to stop the script, but still wanting to return the errors for why I needed to stop the script?!
Really bare bones skeleton:
$errors = array();
function add_error($message, $die = false) {
global $errors;
$errors[] = $message;
if ($die) {
die(implode("\n", $errors));
}
}
If you are using PHP5+ your class can have a destructor method:
public function __destruct() {
die(var_dump($this->errors));
}
You can register a shutdown function.
Add the errors to the current $_SESSION
Add the latest errors to any kind of cache, XML or some storage
If the code 'stops':
// code occurs error
die(print_r($errors));
You can use a trick involving do{}.
do {
if(something) {
// add error
}
if(something_else) {
// add error
break;
}
if(something) {
// add error
}
}while(0);
// check/print errors
Notice break, you can use it to break out of the do scope at any time, after which you have the final error returning logic.
Or you could just what's inside do{} inside a function, and use return instead of break, which would be even better. Or yes, even better, a class with a destructor.

Is it possible to make an object return false by default?

I tried to ask this before, and messed up the question, so I'll try again. Is it possible to make an object return false by default when put in an if statement? What I want:
$dog = new DogObject();
if($dog)
{
return "This is bad;"
}
else
{
return "Excellent! $dog was false!"
}
Is there a way this is possible? It's not completely necessary, but would save me some lines of code. thanks!
No, PHP has no support for operator overloading. Maybe they'll add it in a future version.
Use the instanceof keyword.
For example
$result = Users->insertNewUser();
if($result instanceof MyErrorClass){
(CHECK WHAT WENT WRONG AND SAY WHY)
} else {
//Go on about our business because everything worked.
}
Info is here.
Use this? Not a real neat solution, but does what you want:
<?php
class Foo
{
private $valid = false;
public function Bar ( )
{
// Do stuff
}
public function __toString ( )
{
return ( $this -> valid ) ? '1' : '0';
}
}
?>
Zero is considered false, one is considered true by PHP
I was attempting to do this myself and found a solution that appears to work.
In response to the others who were trying to answer the question by telling the asker to use a different solution, I will also try to explain the reason for the question. Neither the original poster or I want to use an exception, because the point is not to use exception handling features and put that burden on any code we use this class in. The point, at least for me, was to be able to use this class seamlessly in other PHP code that may be written in a non-object-oriented or non-exception-based style. Many built-in PHP functions are written in such a way that a result of false for unsuccessful processes is desirable. At the same time, we might want to be able to handle this object in a special way in our own code.
For example, we might want to do something like:
if ( !($goodObject = ObjectFactory::getObject($objectType)) ) {
// if $objectType was not something ObjectFactory could handle, it
// might return a Special Case object such as FalseObject below
// (see Patterns of Enterprise Application Architecture)
// in order to indicate something went wrong.
// (Because it is easy to do it this way.)
//
// FalseObject could have methods for displaying error information.
}
Here's a very simple implementation.
class FalseObject {
public function __toString() {
// return an empty string that in PHP evaluates to false
return '';
}
}
$false = new FalseObject();
if ( $false ) {
print $false . ' is false.';
} else {
print $false . ' is true.';
}
print '<br />';
if ( !$false ) {
print $false . ' is really true.';
} else {
print $false . ' is really false.';
}
// I am printing $false just to make sure nothing unexpected is happening.
The output is:
is false.
is really false.
I've tested this and it works even if you have some declared variables inside the class, such as:
class FalseObject {
const flag = true;
public $message = 'a message';
public function __toString() {
return '';
}
}
A slightly more interesting implementation might be:
class FalseException extends Exception {
final public function __toString() {
return '';
}
}
class CustomException extends FalseException { }
$false = new CustomException('Something went wrong.');
Using the same test code as before, $false evaluates to false.
I recently had to do something similar, using the null object pattern. Unfortunately, the null object was returning true and the variable in question was sometimes an actual null value (from the function's default parameter). The best way I came up with was if((string)$var) { although this wouldn't work for empty arrays.
Putting something in "an if statement" is simply evaluating the variable there as a boolean.
In your example, $dog would need to be always false for that to work. There is no way to tell when your variable is about to be evaluated in a boolean expression.
What is your ultimate purpose here? What lines of code are you trying to save?
I'm not sure about the object itself. Possible. You could try something like, add a public property to the DogObject class and then have that set by default to false. Such as.
class DogObject
{
var $isValid = false;
public function IsValid()
{
return $isValid;
}
}
And then when you would instantiate it, it would be false by default.
$dog = new DogObject();
if($dog->IsValid())
{
return "This is bad;"
}
else
{
return "Excellent! $dog was false!"
}
Just a thought.
If I understand what your asking, I think you want to do this:
if (!$dog){
return "$dog was false";
}
The ! means not. SO you could read that, "If not dog, or if dog is NOT true"
Under what conditions do you want if($dog) to evaluate to false? You can't do what you've literally asked for, but perhaps the conditioned could be replaced by something that does what you want.
class UserController
{
public function newuserAction()
{
$userModel = new UserModel();
if ($userModel->insertUser()) {
// Success!
} else {
die($userModel->getError());
}
}
}
Or
class UserController
{
public function newuserAction()
{
$userModel = new UserModel();
try {
$userModel->insertUser()
}
catch (Exception $e) {
die($e);
}
}
}
There are a million ways to handle errors. It all depends on the complexity of the error and the amount of recovery options.
How about using an Implicit Cast Operator like the following C# ?
like so:
class DogObject
{
public static implicit operator bool(DogObject a)
{
return false;
}
}
Then you can go...
var dog = new DogObject();
if(!dog)
{
Console.WriteLine("dog was false");
}

Categories