-2

I am trying to make an ARRAY of files and subfolder inside a specific folder. I got success in getting a list of files and subfolders but when I try kept this data in an ARRAY it only show result as expected within LOOP. Once LOOP finished it return EMPTY

Here is full code

<?php
function dirToOptions($path = '../data/vid/', $level = 0) {
    $items = scandir($path);
    $vidCount = 0; $thumbCount = 0;
    foreach($items as $item) {
        // ignore items strating with a dot (= hidden or nav)
        if (strpos($item, '.') === 0) {
            continue;
        }

        $fullPath = $path . DIRECTORY_SEPARATOR . $item;
        // add some whitespace to better mimic the file structure
        $item = str_repeat('&nbsp;', $level * 3) . $item;
        // file
        if (is_file($fullPath)) {
            $rrInt = (int)$level-1;
            if($rrInt == 0){
                $vid['videos'][] = array('name'=>$item, 'link'=>$fullPath);
                echo "<a href='$fullPath'><i for='$rrInt'>$item</i></a><br />";
            }elseif($rrInt == 1){
                $thumb['thumbs'][] = array('name'=>$item, 'link'=>$fullPath);
                echo "<a href='$fullPath'><i for='$rrInt'>$item</i></a><br />";
                var_dump($thumb); //SHOW RESULT HERE
            }
        }
        // dir
        else if (is_dir($fullPath)) {
            // immediatly close the optgroup to prevent (invalid) nested optgroups
            echo "<b label='$level'>$item</b><br />";
            // recursive call to self to add the subitems
            dirToOptions($fullPath, $level + 1);
        }
    }
}

$array = array(); $vid = array(); $thumb = array();

echo '<div>';
dirToOptions();
echo '</div>';

var_dump($vid); // RETURN EMPTY
?>

Thanks to all for support but at last I prefer to use GLOBAL VARS

devROYAL
  • 430
  • 4
  • 12

3 Answers3

1

See PHP - Variable scope. The $vid defined with $vid = array(); is not available inside the function and the $vid defined inside is not available outside. You probably want to return it at the end of the function:

return $vid;

Then assign the return and use it:

$vid = dirToOptions();
var_dump($vid);

But it looks like you're going to have the same issue with $thumb, so change it to use the $vid array:

        }elseif($rrInt == 1){
            $vid['thumbs'][] = array('name'=>$item, 'link'=>$fullPath);
            echo "<a href='$fullPath'><i for='$rrInt'>$item</i></a><br />";
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
0

The EASY answer is to add the line:

global $vid;

To the beginning of your function. This will extend the scope of $vid outside of your function.

Though, I would HEARTILY recommend you follow the other instructions, and return the array from the function instead.

R. Smith
  • 551
  • 4
  • 10
-1

The variables inside and outside of a function are different variables, even if they are named the same. This is what's called the variable's scope. This way your function keeps all its state internally, and doesn't affect anything outside of the function definition (by accident). This makes it harder to introduce bugs because you happened to use the same variable name inside a function as outside it.

The solution is to return the value from the function after building the array inside it:

function dirToOptions($path = '../data/vid/', $level = 0) {
    $vid = array();

    ....

    return $vid;
}

$vid = dirToOptions();
var_dump($vid);

That way everything regarding how dirToOptions work is kept isolated, and you only process the content returned from the function. The interface to the function and what is does is kept clean from any external dependencies.

To handle the recursive part of your code, merge the values returned in each step - or pass a parameter by reference. Using a reference is explicit in the method signature and doesn't blindly create a reference to a variable from the global scope (and can be passed as a local variable from a different function if necessary).

function dirToOptions($path = '../data/vid/', $level = 0) {
    $vid = array();

    ....
    } else {
        // merge this array and the one returned from the child directory
        $vid = array_merge($vid, dirToOptions($fullPath, $level + 1));
    }

    return $vid;
}

$vid = dirToOptions();

.. and as a reference:

function dirToOptions(&$vid, $path = '../data/vid/', $level = 0) {
    $vid = array();

    ....
    } else {
        // pass the reference on further down the recursive calls
        dirToOptions($vid, $fullPath, $level + 1);
    }

    return $vid;
}

dirToOptions($vid);
MatsLindh
  • 49,529
  • 4
  • 53
  • 84
  • check the quoted portion [just updated] of question again – devROYAL Apr 04 '18 at 18:28
  • Using `global` is bad, as this breaks the promise from your function that it isn't going to change anything outside itself. If you _do_ want to do something like that, do it by passing a variable as a reference. For future reference I've updated my answer to show you how you can solve it both with a reference and by just keeping the return values. – MatsLindh Apr 04 '18 at 18:51
  • I appreciate your suggestion but problem is that its not working in my case, don't know why. – devROYAL Apr 04 '18 at 18:56
  • Probably because you're not considering the recursive function call you have inside your code, which I've added examples for. If you wrote this code originally, you should have a decent grasp of the flow of it. – MatsLindh Apr 04 '18 at 18:57