我想用 PHP 和 MySQL 构建一个 Evernote 风格的笔记应用程序。
Evernote 允许顶级文件夹中包含笔记记录。
我想让我的应用程序允许文件夹位于文件夹内,以便顶级文件夹可以有一个子文件夹,然后该子文件夹内有笔记记录。
就像下面这张图:
我有这个 PHP 函数,它将构建上图所示的结构菜单...
此代码构建了所示的菜单
<?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> ' . $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;
}
?>
上面的代码通过调用
_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()
通过扫描服务器上的目录查找文件夹和文件来构建如下所示格式的数组。然后将该数组传递给 tree()
。我的目标是让一个函数构建相同样式的数组,但来自 MySQL 数据库文件夹和注释记录。
我需要编写一个函数,可以从两个数据库表构建如下所示的数组。
我的数据库表将是
parent
来表示父文件夹。如果笔记本是父笔记本的子文件夹,则笔记本 ID 将进入父字段。 0 == 父级文件夹。parent
列可链接到笔记本的 ID。代码:
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
)
除非您想让查询变得极其复杂,否则我会做更多的事情,获取所有记录并使用脚本构建数组。像这样的东西:
脚本现在包括数据库内容(更新):
//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);
这应该可行!我在本地开发环境上进行了测试,并通过一组测试数据得到了这个结果:
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)
它所做的是循环遍历每个结果。当然,您需要将列名称(如 $row['notebook'] 中的列名称)更改为实际列的名称。它将在一层深度上工作。如果您需要更多,则必须进行一些调整。不过,这是一般想法,应该从您的结构中构建一个数组。
快速注释
上面的代码不会是严格友好的。如果您担心警告,上面的代码将为您提供有关未定义键的警告。它会为您创建它们,因为我们都对 PHP 又爱又恨。如果您想保留关键警告,您可以使用
if(array_key_exists())
轻松弹出一些关键检查。
潜在的“陷阱”
这适用于名字。如果您允许“笔记本”使用相同的名称,我建议更进一步,通过 id 构建数组,而不是像笔记本标题那样基于文本的列。从那里,您需要在每个笔记本中添加一个带有名称本身的新密钥。我在制作此脚本时复制了您在示例中提供的数组,但我确实想绝对确定您理解此方法涉及的潜在(令人沮丧的)“陷阱”。
如果您有任何疑问,请告诉我,希望这会有所帮助。