【问题标题】:Convert Recursive Directory Listing to MySQL Table将递归目录列表转换为 MySQL 表
【发布时间】:2017-03-23 15:54:45
【问题描述】:

我需要列出给定父文件夹中的所有文件/文件夹,并将其转储到 mysql。

到目前为止,我有:

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$dir = '/home/kevinpirnie/www';

function dirToArray( $dir ) {
    $result = array();
    $cdir = scandir($dir);
    foreach ($cdir as $key => $value) {
        if (!in_array($value, array(".", "..")))  {
            if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){
                $result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value);
            } else {
                $result[] = $value;
            }
        }
    }
    return $result;
}

$res = dirToArray($dir);

echo '<hr />';
echo '<pre>';
print_r($res);
echo '</pre>';

我坚持的是如何将ID's 分配给目录,然后将它们与它们的父级ID's 相关联。

现在,这段代码可以满足我的需要,我只需要能够将其转换为 mysql 插入语句,同时保持关联结构,我在漫长的一周工作中脑残。

最后,我希望有一个类似于以下的表结构:

文件ID、文件夹ID、父文件夹ID、文件名

我该怎么做?

【问题讨论】:

  • 你需要先插入你的父母,这样你就可以得到他们的 Id 作为回报并将这些 Id 设置为子目录的 parentId。如果您使用像 Doctrine 这样的 ORM,它会为您完成。
  • 因为这是我的要求
  • 如果您对数据库结构不太挑剔,您可以将实际目录存储为“键”值。然后,从起点开始,您只需查询所有具有以起点的“键”开头的键的条目,而无需连接。
  • 文件夹和父文件夹有什么区别?请你举个例子好吗?你的数据库的架构是什么?

标签: php mysql recursion


【解决方案1】:

试试这样的:

function dirToDb($res, $parentId = 0)
{
    foreach ($res as $key => $value) {
        if (is_array($value))  {
            $db->exec("insert into table (path, parentId) VALUES (?, ?)", [$key, $parentId]);
            dirToDb($value, $db->fetch("SELECT LAST_INSERT_ID()"));
        } else {
            $db->exec("insert into table (path, parentId) VALUES (?, ?)", [$value, $parentId]);
        }
    }
}

$res = dirToArray($dir);

dirToDb($res);

【讨论】:

  • 我贴出来的数组怎么办?
  • 什么意思?你首先调用你的方法 dirToArray() 并且结果必须传递给 dirToDb()
  • 我的意思是设置 ID
  • 你应该使用AUTOINCREMENT,然后MySQL会处理剩下的事情
  • 你可以使用 UUID。有很多库和一些mysql函数
【解决方案2】:

我稍微修改了您的代码。现在对于每个目录,

index 0 指向目录索引

index 1 指向父目录索引

索引 2,3,....n 指向文件

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$dir = '/home/kevinpirnie/www';

$GLOBALS['I'] = 0; // root folder given index 0

function dirToArray( $dir , $parent) {
    $result = array();
    $cdir = scandir($dir);
    foreach ($cdir as $key => $value) {
        if (!in_array($value, array(".", "..")))  {
            if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){

                $result[$value] = [++$GLOBALS['I']]; // add folder index
                $result[$value][] = $parent; // add parent folder index

                $result[$value][] = dirToArray($dir . DIRECTORY_SEPARATOR . $value, $GLOBALS['I']);
            } else {
                $result[] = $value;
            }
        }
    }
    return $result;
}

$res = dirToArray($dir, $GLOBALS['I']);

echo '<hr />';
echo '<pre>';
print_r($res);
echo '</pre>';
echo '</pre>';

您现在可以使用类似的递归循环将数据直接插入到 mysql 表中(如果您不想使用 mysql 自动生成的 id)

如果你想使用自动生成的mysql id,你应该分两次插入。在第一遍插入文件夹数据并从 mysql insert id 函数中获取 id。然后创建一个关联数组映射

$array_map[$current_folder_id] = mysqli_insert_id()

然后在第二次递归中更新这个id

【讨论】:

    【解决方案3】:

    我认为您也需要将文件夹名称作为记录插入数据库,否则您将无法获得父 ID。但是,在您的结果中,文件夹名称作为记录项丢失。我修改了您的代码,假设您不需要将结果作为数组而只需要 SQL 语句。

    <?php
    $qry = array();
    $result = $conn->query("SELECT MAX(FileID) as lastid FROM YOUR-TABLE-NAME-HERE");
    $row = $result->fetch_assoc();
    $id = $row['lastid'];
    function dirToSql($dir, $parent) {
      global $qry;
      global $id;
      $result = array();
      $cdir = scandir($dir);
      foreach($cdir as $key => $value) {
        if(!in_array($value, array('.', '..'))) {
            $id++;
            $qry[] = "('".$id."', '".$dir."', '".$parent."', '".$value."')";
            if(is_dir($dir . DIRECTORY_SEPERATOR . $value)) {
                dirToSql($dir . DIRECTORY_SEPERATOR . $value, $id);
            }
        }
      }
      return $qry;
    }
    
    $dir = '/home/kevinpirnie/www';
    $sql = dirToSql($dir, 0);
    
    //Here is your SQL Statement
    echo $qry = "INSERT INTO YOUR-TABLE-NAME-HERE (`FileID`, `FolderID`, `ParentFolderID`, `FileName`) VALUES ".implode(',', $sql);
    

    如果需要,您可以优化代码和查询

    【讨论】:

      【解决方案4】:

      你的 Mysql 目录表中的每一行都有三列 -

      目录 ID、目录名称、父 ID

      对于每次插入,父 ID 将连续指定当前目录的父目录。对于根目录,父 id 为 0

      【讨论】:

        【解决方案5】:

        构建数据库的一种非常有用的方法是使用嵌套集。 Joomla 将其用于文章类别等内容。这些可以无限嵌套在彼此之下。

        enter link description here

        【讨论】:

          猜你喜欢
          • 2012-12-20
          • 2020-05-24
          • 1970-01-01
          • 1970-01-01
          • 2015-12-03
          • 1970-01-01
          • 2013-12-22
          • 2012-02-14
          • 2011-03-10
          相关资源
          最近更新 更多