-1

I'm struggling with a recursive function as it seems to be overwriting the variables in the foreach loop. Can someone help me identify how to fix this? What I'm trying to accomplish is a folder tree, found in a SQL database, where the parent folder holds children and grandchildren. I'm getting children, but only grandchildren of the first child. I believe it's overwriting the statement somewhere.

function locateFolders($folderId, $arrIn = array()) {
    $con = $_SESSION["dbConnection"]->conStr;
    array_push($arrIn, $folderId);
    // Select all folders that have this id as the parent folder id
    $statement = "SELECT * FROM folders WHERE parentid='$folderId'";
    $result = mysqli_query($con, $statement) or die(mysqli_error($con));
    
    if (mysqli_num_rows($result) > 0) {
        while ($r = mysqli_fetch_assoc($result)) {
            array_push($arrIn, $r["id"]);
            $statement2 = "SELECT * FROM folders WHERE parentid='".$r["id"]."'";
            $result2 = mysqli_query($con, $statement) or die(mysqli_error($con));
            while ($row = mysqli_fetch_assoc($result2)) {
                return locateFolders($row["id"], $arrIn);
            }
        }
    }
    $arrIn = array_unique($arrIn);

    return $arrIn;
}
  • 1
    **Warning:** You are wide open to [SQL Injections](https://stackoverflow.com/a/60496/1839439) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Aug 06 '20 at 12:05
  • 1
    It is a very bad idea to use `die(mysqli_error($conn));` in your code, because it could potentially leak sensitive information. See this post for more explanation: [mysqli or die, does it have to die?](https://stackoverflow.com/a/15320411/1839439) – Dharman Aug 06 '20 at 12:05

1 Answers1

0

It took several days but I finally figured this out. I wanted to share just in case someone else has a similar problem. Note that the code may not be "proper" or there may be a better way of doing this, but it is working for me. I have several smaller functions being called here, so if you have questions, that's why:

    function findAllFolders($parentId, $folderList = array()) {
    /// This function finds all the user's allowed directories and returns an array of id's.
    /// Starting with the parentId, all directories within are added to the array.
    // Is the folder valid?
    if ($parentId > 1) { // The smallest folder id in my database is 1
        // Does it still exist in the Database?
        if (!mysqli_num_rows(select("folders","id=$parentId")) > 0) {
            return false;
        }
        // If so, add it to the array.
        array_push($folderList, $parentId);
        // Find all folders that have this as its parent folder.
        $subfolders = select("folders", "parentid=$parentId");
        
        if (mysqli_num_rows($subfolders) > 0) {
            while ($row = mysqli_fetch_assoc($subfolders)) {
                array_push($folderList, $row["id"]);
            }
        }
    }
    foreach ($folderList as $folder) {
        $result = select("folders", "parentid=$folder");
        while ($row = mysqli_fetch_assoc($result)) {
            if (!in_array($row["id"],$folderList)) {
                return findAllFolders($row["id"],$folderList);
            }
        }
    }

    // Remove all duplicates.
    array_unique($folderList);
    return $folderList;
}
///HELPER FUNCTION:
function select($table, $condition="1", $columns="*") {
    $sql = "SELECT $columns FROM $table WHERE $condition";
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // note: $conStr is a global variable connection I created for my program.
    return mysqli_query($conStr, $sql);
}