将递归目录列表转换为MySQL表

7

我需要列出给定父文件夹中的所有文件/文件夹,并将其转储到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,然后将它们与其父ID关联起来。目前,这段代码基本上可以满足我的需求,我只需要能够将其转换为mysql插入语句,同时保持关联结构,但由于工作时间过长,我的大脑已经死掉了。最终,我希望拥有类似以下表结构:FileID、FolderID、ParentFolderID和FileName。我该怎么做?

你需要先插入你的父目录,这样你就可以得到它们的ID并将这些ID设置为子目录的parentId。如果你使用像Doctrine这样的ORM,它会自动完成这个过程。 - solarc
因为这是我的要求。 - Kevin
如果您对数据库结构不是特别挑剔,可以将实际目录存储为“键”值。然后,从起始点开始,您只需查询所有具有以起始点的“键”开头的键的条目,无需进行连接即可完成。 - A Smith
文件夹(Folder)和父文件夹(ParentFolder)有什么区别?你能举个例子吗?你的数据库模式是什么? - borracciaBlu
5个回答

4
尝试像这样做:

尝试像这样做:

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);

如何将其作为我发布的数组来执行? - Kevin
我是指在其中设置ID。 - Kevin
你应该使用AUTOINCREMENT,MySQL会自动处理剩下的部分。 - Sebastian
这是正确的@manian,我确实希望在插入之前获得ID。只有一个人会连接,并且实际上这个脚本只会从cli运行。 - Kevin
1
你可以使用UUID。有许多库和一些MySQL函数可供使用。 - Mehmet SÖĞÜNMEZ
显示剩余3条评论

2
我稍微修改了你的代码。现在对于每个目录,
索引0指向目录索引
索引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自动生成的id)直接将数据插入到mysql表中。

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

$array_map[$current_folder_id] = mysqli_insert_id()

然后在第二个递归过程中更新此id。


0

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

目录ID、目录名称、父ID

对于每个插入操作,父ID将指定当前目录行的父目录。对于根目录,父ID为0


0
一个非常有用的数据库结构方式是使用嵌套集。Joomla在文章分类等方面使用了这种结构方式。这些东西可以无限嵌套。

输入链接描述


0

我认为你需要将文件夹名称作为记录插入到数据库中,否则你将无法获得父级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);

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接