-1

I have a problem with a recursive function in PHP which returns a JSON object. When the the condition is met to run the function a second time I always get an empty object as result {}. Everything is executed as it would be in the first run, but I always get an empty result.

Here is my code (very much simplified, yet functioning):

public function run()
{
    $result = null;

    // .......
    // there is alot other stuff here, that all runs 
    // perfectly through also the second run
    // ......

    // Conditional Routing
    if($this->wfProfile->autoprocess){
        // select new wfProfile and go again.
        $this->autoprocess(function($data){
            if($data['error']==0){
                $result = null;
                $this->run(); // from here we start over !
            }else{
                return $data;
            }
        });
    }else{
        return ['error'=>0,'message'=>'all good']; // this is where it should go at the end of second loop
    }
}

There is no place in the whole class, that would return an empty JSON object. Something must be here, that I'm doing wrong or what I'm overseeing.

Edit (I don't think this helps)

private function autoprocess($callback)
{
    if(is_callable($callback)){
        $possibleWFprofiles = WfProfile::where('statusNow', $this->wfRequest->status)->where('conditionalRouting', 1)->get();
        if($possibleWFprofiles->count() == 0){
            // configuration error....
            $result = ["error"=>1, 'message'=>"Unable to find Conditional Routing enabled WfProfiles: ".$this->wfRequest->status];
        }
        foreach($possibleWFprofiles as $possibleWfProfile){
            if(array_search($possibleWfProfile->crFieldname, $this->wfRequestFields)===false){
                // fieldname wrongly configured
                $result = ["error"=>1, 'message'=>"Unable to find field ".$possibleWfProfile->crFieldname];
            }
            // see if this is the right one
            if($this->wfRequest[$possibleWfProfile->crFieldname] == $possibleWfProfile->crValue){
                  $this->wfProfile = $possibleWfProfile;
                  $result = ['error'=>0,'message'=>'Off to loop 2'];
            }
        }
        call_user_func($callback, $result);
    }
}
Edwin Krause
  • 1,766
  • 1
  • 16
  • 33

3 Answers3

3

When you make a return $data, inside a anonymous function, it will not be a run's return.

You are not doing nothing with this return in your autoprocess function.

You need to return something in autoprocess and then return in your if:

if($this->wfProfile->autoprocess){
    // select new wfProfile and go again.
    return $this->autoprocess(function($data){
        if($data['error']==0){
            $result = null;
            return $this->run(); // from here we start over !
        }else{
            return $data;
        }
    });
}else{
    return ['error'=>0,'message'=>'all good']; // this is where it should go at the end of second loop
}
Bezerra
  • 146
  • 10
  • 1
    But not only `return $this->run()`, he needs to return `autoprocess` as well. And adjust `autoprocess` function to return something :) – Bezerra Apr 09 '18 at 16:11
  • 1
    Yes I see that and tried to explain it to him. Thank you for showing me how to better explain it! ;-) – Popmedic Apr 09 '18 at 16:18
  • This makes sense... although I changed my code already completely and returned something (as it was originally) from the $this->autoprocess() function. I will post it as an alternative here and accept this one as the correct answer and popmedic upvote for effort :-) – Edwin Krause Apr 09 '18 at 16:42
1

You need to return your value, for example take this:

function callback($func, $val) {
    return call_user_func($func, $val);
}

function run($val) {
    if ($val < 10) {
        callback(function($val) { return run($val + 1); }, $val);
    } 
    return $val;
}

print(run(0));

this will print empty, but if you do:

function callback($func, $val) {
    return call_user_func($func, $val);
}

function run($val) {
    if ($val < 10) {
        return callback(function($val) { return run($val + 1); }, $val);
    } 
    return $val;
}

print(run(0));

it will print 10

Your function:

public function run()
{
    $result = null;

    // lets say this is true...
    if($this->wfProfile->autoprocess){
        // now we are here, where does this return a value???
        $this->autoprocess(function($data){
            // if it goes here, it never returns a value.
            if($data['error']==0){
                $result = null;
                $this->run(); // from here we start over !
            }else{ // if it returns here it still just returns to 
                   // $this->autoprocess, which might return to the
                   // original run function, but you don't seem to be
                   // returning its return either...
                return $data;
            }
        });
    }else{
        return ['error'=>0,'message'=>'all good']; // this is where it should go at the end of second loop
    }
}
Popmedic
  • 1,791
  • 1
  • 16
  • 21
1

At the end I chose the imho less elegant way to solve this, so I used goto instead of calling the function again. This is easy to read and to debug/extend in future. So here we go:

public function run()
{
  startover:
    $result = null;

    // more stuff going on here

    // Conditional Routing
    if($this->wfProfile->autoprocess){
        // select new wfProfile and go again.
        $result = $this->autoprocess();
        if($result['error']==0){
              goto startover; // easiest way :-)
        }else{
              return $result;
        }

    }else{
        return ['error'=>0,'message'=>'all good'];
    }
}

and here the autoprocess function

private function autoprocess()
{
    $possibleWFprofiles = WfProfile::where('statusNow', $this->wfRequest->status)->where('conditionalRouting', 1)->get();
    if($possibleWFprofiles->count() == 0){
        // configuration error....
        return ["error"=>1, 'message'=>"Unable to find Conditional Routing enabled WfProfiles: ".$this->wfRequest->status];
    }
    foreach($possibleWFprofiles as $possibleWfProfile){
        if(array_search($possibleWfProfile->crFieldname, $this->wfRequestFields)===false){
            // fieldname wrongly configured
            return ["error"=>1, 'message'=>"Unable to find field ".$possibleWfProfile->crFieldname];
        }
        // see if this is the right one
        if($this->wfRequest[$possibleWfProfile->crFieldname] == $possibleWfProfile->crValue){
            $this->wfProfile = $possibleWfProfile;
            return ['error'=>0,'message'=>'Off to loop 2'];
        }
    }
}
Edwin Krause
  • 1,766
  • 1
  • 16
  • 33