【问题标题】:PHP: Tricky Nested Loop with select [duplicate]PHP:带有选择的棘手嵌套循环[重复]
【发布时间】:2017-03-24 20:54:35
【问题描述】:

我当前的项目有问题。

我的数据库中有这个:

ID ---- FOLDERID ---- 描述

1 ---- 0 ---- => 根文件夹(不能删除)

2 ---- 1 ---- =>第一个文件夹(对根文件夹的引用)

3 ---- 1 ---- => 第二个文件夹(也指根目录)

4 ---- 2 ---- => 第一个文件夹中的子文件夹

5 ---- 4 ---- => 子文件夹中的子文件夹

这将显示如下:

  1. 第一个文件夹
    1. 子文件夹
        1. 子文件夹中的子文件夹
  2. 第二个文件夹

好的,所以当我想删除第一个文件夹时,我也想删除所有子文件夹。

我该如何处理?

我知道我需要一个带计数器的循环,但我不知道该怎么做。

这就是我所拥有的:但仅适用于 3 个文件夹:

     $del_id = [];

    do {
        $count = \DB::table('files')
            ->select('id', 'foldersID')
            ->where('userID', '=', \Auth::user()->id)
            ->where('foldersID', '=', $id)
            ->count();

        //count = 1

        if ($count == 0) {

            \DB::table('files')
                ->where('userID', '=', \Auth::user()->id)
                ->where('id', '=', $id)
                ->delete();

        } else {
            //hier
            $_id = $id; //2

            for ($i = 0; $i <= $count; $i++) { //1 mal

                $_files = \DB::table('files')
                    ->select('id')
                    ->where('userID', '=', \Auth::user()->id)
                    ->where('foldersID', '=', $_id)
                    ->get();

                //3

                $files = json_decode($_files, true);

                //return print_r($files);
                // return count($files);
                for ($i = 0; $i <= count($files) - 1; $i++) {
                    array_push($del_id, $files[$i]);
                }
               //3 && 4
            }

            for ($i = 0; $i <= count($del_id) - 1; $i++) {
                $_files = \DB::table('files')
                    ->select('id')
                    ->where('userID', '=', \Auth::user()->id)
                    ->where('foldersID', '=', $del_id[$i])
                    ->get();

                $files = json_decode($_files, true);
                return $files;

                /*   \DB::table('files')
                    ->where('userID', '=', \Auth::user()->id)
                    ->where('id', '=', $del_id[$i])
                    ->delete();
            */
             }

            \DB::table('files')
                ->where('userID', '=', \Auth::user()->id)
                ->where('id', '=', $id)
                ->delete();

        }
    } while ($count >= 1);

谁能帮帮我?

提前致谢。

【问题讨论】:

    标签: php database loops for-loop foreach


    【解决方案1】:

    您需要使用递归来执行此操作。基本上,创建一个删除文件夹的函数。当函数被调用时,它会检查它是否有任何子文件夹,如果有,它会使用子文件夹的 id 调用自己。

    下面我包含了用于测试的 SQL 以及显示递归方法的 PHP 脚本。

    SQL 创建“测试”数据库

    CREATE DATABASE /*!32312 IF NOT EXISTS*/ `testing`;
    
    USE `testing`;
    
    DROP TABLE IF EXISTS `files`;
    CREATE TABLE `files` (
      `id` int(3) NOT NULL AUTO_INCREMENT,
      `folderid` int(11) NOT NULL,
      `description` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
    
    LOCK TABLES `files` WRITE;
    INSERT INTO `files` VALUES (1,0,'root folder'),(2,1,'first folder'),(3,1,'second folder'),(4,2,'sub of first folder'),(5,4,'sub of sub folder');
    UNLOCK TABLES;
    

    使用递归的 PHP 脚本

    <?php
    
    delete_folder(2);
    
    
    function delete_folder($folder_id) {
        $servername = "localhost";
        $username = 'root';
        $password = 'my_password';
        $dbname = "testing";
    
        // Create connection
        $conn = mysqli_connect($servername, $username, $password, $dbname);
        // Check connection
        if (!$conn) {
            die("Connection failed: " . mysqli_connect_error());
        }
    
        $table  = "files";
    
        // find subfolders
        $sub_folders = "select id from $table where folderid = $folder_id";
        $result = $conn->query($sub_folders);
    
        if($result->num_rows > 0) {
            while($row = $result->fetch_assoc()) {
                echo "found sub folder with id: ".$row["id"]." - recursing\n";
                delete_folder($row["id"]); // calls itself to delete subfolder.
            }
        }
    
        // delete this folder
        $delete_sql = "delete from $table where id = $folder_id";
        echo "deleting folder with id: $folder_id";
        if($conn->query($delete_sql) === TRUE) {
            echo " - success\n";
            return;
        } else {
            echo " - failed\n";
            die("Failed to delete folder");
        }
        return;
    }
    
    ?>
    

    创建数据库并运行脚本示例

    导入我们的数据:

    root@zim:~/testing# mysql -p < testing.sql
    Enter password:
    

    查看表格中的内容:

    root@zim:~/testing# mysql -p -e 'select * from files' testing;
    Enter password:
    +----+----------+---------------------+
    | id | folderid | description         |
    +----+----------+---------------------+
    |  1 |        0 | root folder         |
    |  2 |        1 | first folder        |
    |  3 |        1 | second folder       |
    |  4 |        2 | sub of first folder |
    |  5 |        4 | sub of sub folder   |
    +----+----------+---------------------+
    

    运行我们的脚本:

    root@zim:~/testing# php db_recursion.php
    found sub folder with id: 4 - recursing
    found sub folder with id: 5 - recursing
    deleting folder with id: 5 - success
    deleting folder with id: 4 - success
    deleting folder with id: 2 - success
    

    检查表中的内容:

    root@zim:~/testing# mysql -p -e 'select * from files' testing;
    Enter password:
    +----+----------+---------------+
    | id | folderid | description   |
    +----+----------+---------------+
    |  1 |        0 | root folder   |
    |  3 |        1 | second folder |
    +----+----------+---------------+
    

    【讨论】:

    • 另外,我可能应该提到,如果您有超过 100 个嵌套文件夹,您将遇到运行时错误。这可以增加:stackoverflow.com/questions/4293775/…
    • 非常感谢,你帮了我很多!我对递归一无所知。但现在对我来说很有意义。明天晚上(德国时间),我将在您的解决方案中发布我的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    相关资源
    最近更新 更多