1

I have an array of data that is created by a function, but the function will not return the data.

Here is the function:

/**
 * Takes in a legacy id and returns new id.
 */
function my_function($data) {
  foreach ($data as $info) {
    $new_info = my_other_function($info);
    $new_data[] = $new_info;
  }

  return $new_data;
}

Here is where it's called:

$data = array('7245');
echo 'test1';                   // prints out test1
$new_data = my_function($data);
print_r($new_data);                 // DOES NOT PRINT ANYTHING, SAME RESULTS WITH VAR_DUMP()
echo 'test2';                   // prints out test2

However if I change the function to the following, it prints out while in the function, but still does not print out the returned value:

function my_function($data) {
  foreach ($data as $info) {
    $new_info = my_other_function($info);
    $new_data[] = $new_info;
  }
  print_r($new_data);
  return $new_data;
}

So now this:

$data = array('7245');
echo 'test1';                   // prints out test1
$new_data = my_function($data);
echo 'test2';                   // prints out test2
print_r($new_data);                 // DOES NOT PRINT ANYTHING, SAME RESULTS WITH VAR_DUMP()

Prints out this:

test1
array(0=>9876)
test2
// RETURNED VALUE SHOULD BE HERE BUT IT IS NOT

EDIT:

Since it seems this is essientally impossible, I'm adding the original function, which lives in a Drupal module. I have test all other functions called in this function and they work perfectly on their own.

$file_data = '7024';
$ids = tdm_migration_import_file($file_data, $inline='no');

function tdm_migration_import_file($data, $inline) {
  // create base array
  $new_data = array();
  if (!is_array($data)) {
    $data = array($data);
  }
  // if we are reprocessing this data, remove the first element (flag) of
  // the array
  // dpm($data, 'incoming data');
  if (isset($data['reprocess'])) {
    unset($data['reprocess']);
  }
  foreach ($data as $file_data) {
    if (trim($file_data) == '') {
      continue;
    }
    // check to see if this data is coming from a text block or not
    if ($inline == 'no') {
      // given a path or fid
      if (is_numeric($file_data)) {
        // given an int (fid)
        $legacy_fid = $file_data;
        $legacy_file_path = tdm_migration_get_legacy_file_data($legacy_fid);
        // set the flag to reprocess this data
        $new_data['reprocess'] = 'yes';
        // add file path to new data for reprocessing
        $new_data[] = $legacy_file_path;
      } else {
        // given a string (path or uri/url)
        $legacy_file_path = $file_data;
        $path_data = tdm_migration_extract_path_data($legacy_file_path);
        // // if the directory doesn't exist we create it and make sure permissions
        // allow for writing by the server
        file_prepare_directory($path_data['public_path'], FILE_CREATE_DIRECTORY);
        // check to see if the file already exists in file structure
        $realpath = drupal_realpath($path_data['public_file_path']);
        if (!file_exists($realpath)) {
          // create new file and get new fid
          $fid = tdm_migration_create_file($path_data['legacy_file_url'], $path_data['public_file_path'], $data='fid');
        } else {
          // get the existing file id
          $fid = tdm_migration_get_existing_file_data($path_data['public_file_path']);
        }
        $new_data[] = $fid;
      }
    } else {
      // given a body of text, find <img> tags and extract the src attributes
      $legacy_paths = tdm_migration_extract_img_srcs($file_data);
      $replacement_paths = array();
      foreach ($legacy_paths as $legacy_path) {
        $path_data = tdm_migration_extract_path_data($legacy_path);
        file_prepare_directory($path_data['public_path'], FILE_CREATE_DIRECTORY);
        $realpath = drupal_realpath($path_data['public_file_path']);
        if (!file_exists($realpath)) {
          $new_path = tdm_migration_create_file($path_data['legacy_file_url'], $path_data['public_file_path'], $data='path');
        } else {
          $new_path = $public_file_path;
        }
        // aggregate old and new paths
        $replacement_paths[$legacy_path] = $new_path;
      }
      // replace all old paths with new paths in original text
      $new_file_data = tdm_migration_replace_text($file_data, $replacement_paths);
      $new_data[] = $new_file_data;
    }
  }
  if (isset($new_data['reprocess']) && $new_data['reprocess'] == 'yes') {
    // dpm($new_data, 'reprocessing');
    tdm_migration_import_file($new_data, $inline='no');
  } else {
    dpm($new_data, 'new-data'); // THIS PRINTS OUT!!!!!!
    return $new_data;
  }
}

EDIT2: There seems to be some confusion as to what this is doing so I will explain the steps in plain english.

  1. $data = '7204'; The data variable is being set to a string of numbers
  2. Place $data in an array, also called $data.
  3. Check to see if the key 'reprocess' is set in $data, if it is, remove it
  4. Itterate through the $data array, individual elements of the array now called $file_data (this function downloads files based on migration needs).
  5. If the element is blank, skip it and go to the next element
  6. Check if the $inline variable is set, if it is we are dealing with HTML (not the issue at hand) In this case the data is a string of numbers. $inline is never set to 'yes'.
  7. Check to see if the element is numeric, in this case IT IS NUMERIC
  8. Get the relative path, stored in the old database, using tdm_migration_get_legacy_file_data(). The new data looks something like: sites/default/files/somefile.jpg
  9. Set reprocess to yes in the new_data
  10. Add the returned file path to the new_data array.
  11. Now the function goes to the bottom with the last if/else and checks if reprocess isset and if it is equal to yes - in this case IT IS!
  12. Since reprocess is equal to yes, we run through the function again with the given string (path)!
  13. UNSET reprocess!
  14. Itterate through the data again
  15. Not inline
  16. Not numeric! SO REPROCESS IS NEVER SET NOW!!!
  17. Get path data (returns things like the new server path, etc) - verified working
  18. Prepare the directory with write privleges and create it if it doesn't already exist
  19. Check if the file already exists on the server
  20. If it doesn't, then it creates the file and adds the file info to the database by running tdm_migration_create_file(), which returns the file id ($fid). - verified working - If it does exist, it just checks the database for the file id - verified working
  21. Add the file id to $new_data.
  22. Now at the bottom of the function, it goes to the ELSE because REPROCESS IS NOT SET and should return the data

This last part is what is wrong. If add the line dpm($new_data, 'new-data'); before the return, it prints out exactly what it should. For the uninitiated, dpm is a drupal fucntion that prints out data in a clean format. If it change the dpm line to var_dump($new_data); die(); - it STILL prints the data, but the function WILL NOT RETURN IT!

23
  • In short: this is kind of impossible. Please provide a block of code which we can copy, paste and run as is that shows this exact problem. Commented Aug 28, 2014 at 18:53
  • 1
    Seems to work fine to me: eval.in/184938 Commented Aug 28, 2014 at 18:53
  • @deceze - trying to find a way to do that now...this is in a drupal module and is connecting to two databases to retrieve data...there is no short way for me to explain it, so i will work on it and update the question. Commented Aug 28, 2014 at 18:58
  • Try var_dump() instead of print_r(). It should print NULL if it's actually not putting anything in there. Commented Aug 28, 2014 at 18:59
  • @Samsquanch - the actual function i'm using to print is dpm() which is a drupal function, but I figured i would put print_r here for those that don't know Drupal. Same results with var_dump() Commented Aug 28, 2014 at 19:00

1 Answer 1

4

Your function does not return data here!

  ...
  if (isset($new_data['reprocess']) && $new_data['reprocess'] == 'yes') {
    // vvvvvvvvvvvvvvvvvvvvv
    tdm_migration_import_file($new_data, $inline='no');
    // ^^^^^^^^^^^^^^^^^^^^^
  } else {
    return $new_data;
  }

It doesn't matter that the function calls itself again. It could call any function, that's irrelevant. There's no return statement here, so the function doesn't return data if it goes into the if branch. Fix it:

 return tdm_migration_import_file($new_data, $inline='no');

Very typical newbie recursive call error.


Apparently I need to make more clear why this doesn't work as you think. First: there's nothing special about recursion!. You're just calling a function. It doesn't matter that it's the same function you're currently in. There's no special magic that happens in this case.

Take this example function:

function foo() {
    if (rand(0, 1)) {
        bar();
    } else {
        return true;
    }
}

This function will only return true half the time. The other half, it will call a function bar which does who-knows-what, but it will not return any value from that call.

Now substitute bar() with foo(). It doesn't change anything about the behaviour I described above. The function will still only return data half the time. If there's no return statement, it doesn't return data. Plain and simple. Not even from recursive calls.

Calling a function recursively does not "restart" the function, it creates another function call subject to the same rules as any other function call. Your function does not return data if reprocess is equal to yes, period.

Sign up to request clarification or add additional context in comments.

14 Comments

Nice catch. I didn't realize it was a recursive call.
If that's the case, then I go back to my answer reverts to "magical PHP".
@CR47 I added a longer explanation to disprove your step 12 and/or 22.
@CR47 No, it will not work. bar(); does not return data. return bar(); returns data.
@CR47 Just literally read aloud what the code does: If reprocess is true, call [a function], else return data. Data is only returned in one of two cases here.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.