简体   繁体   English

如何从MySQL数据库记录生成PHP数组以实现多级文件夹结构

[英]How to generate a PHP array from MySQL database record for multi-level folder structure

I am wanting to build an Evernote style note app with PHP and MySQL. 我想用PHP和MySQL构建Evernote风格的笔记应用程序。

Evernote allows top level folders with note records in them. Evernote允许其中包含便笺记录的顶级文件夹。

I would like to make my app allow folders to be inside of folders so a top level folder can have a child folder which then has note records inside of the child folder. 我想让我的应用程序允许文件夹位于文件夹内,以便顶层文件夹可以具有子文件夹,然后在子文件夹内具有注释记录。

Like this image below... 就像下面的这张图...

在此处输入图片说明


I have this PHP function which will build the structure menu shown in the image above... 我有这个PHP函数,它将构建上图所示的结构菜单...

This code build the menu shown 此代码构建显示的菜单

<?php
function tree($array, $parent, $parts = array(), $step = 0) {

    if (!count($array)) {
        return '';
    }

    $tid = ($step == 0) ? 'id="tree"' : '';
    $t = '<ul class="unstyled" '.$tid.'>';

    foreach ($array as $key => $item) {
        if (is_array($item)) {
            $open = $step !== false && (isset($parts[$step]) && $key == $parts[$step]);

            $t .= '<li class="directory'. ($open ? ' open' : '') .'">';
                $t .= '<a href="#" data-role="directory"><i class="glyphicon glyphicon-folder-'. ($open ? 'open' : 'close') .'"></i>&nbsp; ' . $key . '</a>';
                $t .= tree($item, "$parent/$key", $parts, $open ? $step + 1 : false);
            $t .=  '</li>';
        } else {
            $selected = (isset($parts[$step]) && $item == $parts[$step]);
            $t .= '<li class="file'. ($selected ? ' active' : '') .'"><a href="'. $parent .'/'. $item . '">'.$item.'</a></li>';
        }
    }

    $t .= '</ul>';

    return $t;
}
?>

The code above build the tree menu by calling _getTree() 上面的代码通过调用_getTree()构建树菜单

protected function _getTree($dir = LIBRARY)
{
    $return = array('directories' => array(), 'files' => array());

    $items = scandir($dir);
    foreach ($items as $item) {
        if(preg_match($this->_ignore, $item)) {
            if($this->_force_unignore === false || !preg_match($this->_force_unignore, $item)) {
                continue;
            }
        }

        $path = $dir . DIRECTORY_SEPARATOR . $item;
        if (is_dir($path)) {
            $return['directories'][$item] = $this->_getTree($path);
            continue;
        }

        $return['files'][$item] = $item;
    }

    uksort($return['directories'], "strnatcasecmp");
    uksort($return['files'], "strnatcasecmp");

    return $return['directories'] + $return['files'];
}

_getTree() above builds an array in the format shown below by scanning directories on server looking for folders and files. 上面的_getTree()通过扫描服务器上的目录以查找文件夹和文件,以下面显示的格式构建一个数组。 It then passes that array into tree() . 然后将数组传递给tree() My goal is to make a function build this same style array but from MySQL Database folder and note records. 我的目标是使一个函数从MySQL数据库文件夹和注释记录构建相同的样式数组。

Can anyone help me with a function that could build array like below from 2 database tables. 任何人都可以通过一个可以从2个数据库表构建如下数组的函数来帮助我。

MY database tables will be 我的数据库表将是

  • notebooks with column name parent to denote the parent folder. 列名称为parent 笔记本表示父文件夹。 THe notebook ID will go into parent field if the notebook is a child folder of a parent notebook. 如果笔记本ID是父笔记本的子文件夹,则该笔记本ID将进入父字段。 0 == parent level folder. 0 ==父级文件夹。
  • notes with parent column to be linked to ID of notebook. 带有parent列的注释要链接到笔记本的ID。

Any help greatly appreciated? 任何帮助,不胜感激?

Array(
    [top_level_notebook_1] => Array(
            [child_note_of_parent_notebook_1.html] => some_note.html
            [child_level_notebook_1] => Array(
                    [note_1.html] => some_note.html
            )

            [child_level_notebook_2] => Array(
                    [note_2] => cache.js
                    [note_3] => cache.js.md
                    [note_4] => Confirmation-Dialog.js
            )

            [child_level_notebook_3] => Array(
                    [crud.php] => crud.php
                    [error2mysql.php] => error2mysql.php
                    [upload_file_from_remote_url.php] => upload_file_from_remote_url.php
            )

    )

    [top_level_notebook_2] => Array(
            [note_7.html] => some_note.html
    )

    [root_level_note.html] => Dev_Bookmarks.html
)

Unless you want to get incredibly complex with your query, I'd do something more along the lines of getting all records and building an array with your script. 除非您想使查询变得异常复杂,否则我将按照获取所有记录并使用脚本构建数组的方式进行更多操作。 Something like this: 像这样:

Script now including the Database stuff ( Updated ): 现在,脚本包括数据库内容(已更新 ):

//Change these credentials!
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}

$query = "SELECT nb.`name` AS 'notebook', no.`name` AS 'note', (SELECT `name` FROM `notebooks` WHERE `id` = nb.`parent`) AS 'nbparent', no.`parent` AS 'noparent' FROM `notebooks` nb RIGHT JOIN `notes` no ON no.`parent` = nb.`id` WHERE (nb.`active` = 1 OR nb.`active` IS NULL) AND (no.`active` = 1 OR no.`active` IS NULL)";

$result = $mysqli->query($query);

$myArray = array();

while($row = $result->fetch_assoc()){
    if($row['nbparent']){
        if($row['note']) $myArray[$row['nbparent']][$row['notebook']][] = $row['note'];
    } else {
        if($row['note']) {
            if($row['notebook']) $myArray[$row['notebook']][] = $row['note'];
                else $myArray[] = $row['note'];
        }

    }

}

var_dump($myArray);

This should work! 这应该工作! I tested it on my local dev environment and got this result with a set of test data: 我在本地开发环境上对其进行了测试,并通过一组测试数据得到了以下结果:

array (size=4)
  'Parent Notebook1' => 
    array (size=6)
      0 => string 'Note1' (length=5)
      1 => string 'Note2' (length=5)
      2 => string 'Note5' (length=5)
      'Child Notebook1' => 
        array (size=1)
          0 => string 'Note6' (length=5)
      'Child Notebook2' => 
        array (size=1)
          0 => string 'Note7' (length=5)
      'Child Notebook3' => 
        array (size=1)
          0 => string 'Note8' (length=5)
  'Parent Notebook2' => 
    array (size=1)
      0 => string 'Note3' (length=5)
  'Parent Notebook3' => 
    array (size=1)
      0 => string 'Note4' (length=5)
  0 => string 'Note With No Parent :(' (length=22)

What that's doing is looping through each result. 这是在遍历每个结果。 Surely you'll need to change the column names, like in $row['notebook'], to what your actual column is named. 当然,您需要将列名(例如$ row ['notebook']中的名称)更改为实际列的名称。 It'll work one-level deep. 它将深入一层。 If you need more, you'll have to tweak a bit. 如果您需要更多,则必须稍作调整。 This is the general idea, though, and should get an array built from your structure. 不过,这是一般的想法,应该从您的结构中构建一个数组。

Quick Note 快速说明

The code above will not be strict-friendly . 上面的代码将不是严格友好的 If you're concerned with warnings, the above code will give you warnings about undefined keys. 如果您担心警告,上面的代码将为您提供有关未定义键的警告。 It'll create them for you, as we've all grown to love/hate about PHP. 它会为您创建它们,因为我们都已经对PHP产生了爱恨之情。 If you want to keep the key warnings out, you can easily pop in some key checks with if(array_key_exists()) . 如果您想避免按键警告,可以使用if(array_key_exists())轻松弹出一些按键检查。

Potential 'Gotcha' 潜在的“ Gotcha”

This works on names. 这适用于名称。 If you allow the same name for 'notebooks', I'd suggest taking it a step further and building the array by id rather than a text-based column like the title of your notebook. 如果您允许“笔记本”使用相同的名称,建议您更进一步,并通过id而不是像笔记本标题那样的基于文本的列来构建数组。 From there, you'll need to add a new key inside of each notebook with the name itself. 从那里,您需要在每个笔记本内部添加一个名称本身的新密钥。 I replicated the array you provided in your example when making this script, but I did want to be absolutely sure you understood the potential (frustrating) "gotcha" involved with this method. 在制作此脚本时,我复制了您在示例中提供的数组,但我确实想确保您了解此方法涉及的潜在(令人沮丧)“陷阱”。

Let me know if you have any questions, hope this helps. 如果您有任何疑问,请告诉我,希望能对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM