CR47
CR47

Reputation: 923

PHP function is not returning data

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!

Upvotes: 1

Views: 5932

Answers (1)

deceze
deceze

Reputation: 522587

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.

Upvotes: 4

Related Questions