2

I am collecting a series of php files and testing to see if a single function returns valid output. To facilitate the process, all their functions are named identically. So then I can run:

foreach($fileList as $file) {

    require($file);
    echo $testFunction();

}

The problem is that php throws an error 'Cannot redeclare function' since the second file's function is named the same as the first. What I want to do is 'undeclare' a function after I test its output but I know this isn't possible and I'm trying to handle this procedurally. unlink($file) does not remove the instance of the function, unfortunately. Is there a simple way to handle this without using an OOP approach?

UPDATE #1

Using exec() instead of shell_exec() allows me to check err status (which is #2). CHMOD was necessary as user/group prevented execution (security settings on this offline server to be updated once the script is functioning). At this point, it does not echo anything since shell_exec() is returning an error (at least I think so since the output from shell_exec is empty and since exec is returning error #2). Here is an updated test:

$fileList = array('test.php');
foreach($fileList as $file) {
    // load code from the current file into a $code variable,
    // and append a call to the function held in the $testFunction variable
    $code = file_get_contents($file) . "\n" . 'testFunction();';

    // save this to a temporary file
    file_put_contents('test-file.php', $code);

    // execute the test file in a separate php process,
    // storing the output in the $output variable for examination

    //*************** */
    $output=null;
    $retval=null;
    $absPath = realpath('test-file.php');
    chmod($absPath,0777);
    echo $absPath;
    exec($absPath, $output, $retval);
    echo "Returned with status $retval and output:\n";
    print_r($output);
}

UPDATE #2 While you can't undeclare a function, you can repeatedly assign different functions to the same var. For example:

$listOfFunctionNames = array('function1', 'function2', 'function3);
foreach($listOfFunctionNames as $func) {
     $funxion = $func;
     $funxion();
}
George
  • 29
  • 8
  • You cannot "un-declare" a function in PHP, so you're going to have to give the functions different names. – Sammitch Jan 13 '22 at 20:39
  • 1
    or use a namespace – Lawrence Cherone Jan 13 '22 at 21:30
  • @George my bad from an early version of my answer, but revise the `exec` call to `exec("php $absPath", $output, $retval);`, and see if that gets you going. (You may need to put the full path to the php executable too, you can find that by running `which php` from the command line. – quickshiftin Jan 19 '22 at 21:23
  • @quickshiftin Thanks, yes, I'd already nailed the missing exec("php $absPath...)... For some reason, I just can't get any output from php even using a terminal... Working on that. I did, however, come up with a way around my problem - noted above in Update #2. – George Jan 23 '22 at 01:59

1 Answers1

1

You can execute the files in another process, for example (assuming $testFunction is defined in the files), you could do something like this (assuming you are running on Linux):

foreach($fileList as $file) {
    // load code from the current file into a $code variable,
    // and append a call to the function held in the $testFunction variable
    $code = file_get_contents($file) . "\n" . '$testFunction();';

    // save this to a temporary file
    file_put_contents('/tmp/test-file.php', $code);

    // execute the test file in a separate php process,
    // storing the output in the $output variable for examination
    $output = shell_exec('php /tmp/test-file.php');

    // examine output as you wish
}

unlink('/tmp/test-file.php');

EDIT:

Since testFunction does not echo, and instead returns the output to be examined, we can simply modify the test file to echo testFunction();.

$code = file_get_contents($file) . "\n" . 'echo testFunction();'; // <- NOTE: the semi-colon after testFunction();

I noticed my original answer was lacking a semi-colon in the test file, which is probably where the error was coming from. What you can do to ensure it's correct is have this script generate the first test file and terminate early. You can then manually inspect the file for correctness and also use PHP to ensure it's parse-able, from the command line:

php -l /tmp/test-file.php

Note also there are more sophisticated ways you could check correctness of each test file, however I am trying to keep the answer concise, as that is starting to stray into a separate question.

quickshiftin
  • 66,362
  • 10
  • 68
  • 89
  • Thank you! I was not familiar with shell_exec(). The testFunction() I had in mind is slightly different than my example above (apologies). Instead, the testFunction() returns a string and when shell_exec() executes test-file.php, the $output is empty because test-file.php does not 'echo' a value but 'returns' it instead. – George Jan 14 '22 at 16:32
  • Hey @George my pleasure to help! I noticed a missing semi-colon in my original answer, which has been updated. Also, since your function does not `echo` itself that can just be added to the test file. – quickshiftin Jan 18 '22 at 15:44
  • @George looking back at the answer I caught another glaring error, the command needs to be `php /tmp/test-file.php`! – quickshiftin Jan 19 '22 at 21:21