要求:实现类似看云的最基本功能。
大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码,骂我的技术。谢谢
语言:PHP ,框架Thinkphp
要点:如何实现同一页面展示不同内容、实现静态html文件自动更新、PHP如何遍历所有文件以及文件夹、读取文件内容Thinkphp的标签的使用、markdown文件的读取并转码显示。
对了,不是基于数据库的。就是一个特别low的东西
特别提醒 目录和文件夹在本文中指的是一个意思
前端(省略CSS)
wikiz主页由三个<frame> 和 两个<frameset>(框架)组成。
<frame> 头部 head.html
<frame> 左侧目录 index.html
<frame> 内容部分 body.html 分支 one.html、 one_1.html 、one_two.html (分别是章节、一级、二级)[1]
重点是 index.html 和 body.html
index.html 主要负责由后台传过来关于目录和文件的情况,然后按等级展示。
body.html 主要负责由根据左侧目录的变化接收后台传过来的内容,然后展示在body区域
index代码
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
<style>
a:link {
color: green;
text-decoration: none;
}
a:visited {
color: brown;
text-decoration: none;
}
a:hover {
color: darkorange;
text-decoration: none;
}
a:active {
color: sienna;
text-decoration: none;
}
</style>
</head>
<body>
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
{volist name = "test" id="vo"}
<h2>
<a href="index_one.html?file_one={$vo.title}" target="body_right">章节{$vo.title}</a></h2>
{volist name = "vo[ 'lists'] " id="voo"}
<h3><a href="index_one_1.html?file_two={$vo.title}\{$voo.title}" target="body_right">{$voo.title}</a></h3>
{volist name = "voo[ 'lists'] " id="vooo" key ="z"}
<ul>
<li><a href="index_one_2.html?file_three={$vo.title}\{$voo.title}\{$vooo.title}" target="body_right">{$vooo.title}</a></li>
</ul>
{/volist} {/volist} {/volist}
</body>
</html>
body.html 代码
以下三个网页的代码基本上相同,其中最重要的是Markdown的解析,我在网上找了好久,找到GitHub大神的js库,拿来可用,非常感谢。有时间研究一下怎么把markdown的标签转码为html。
<!DOCTYPE html>
<html>
<head>
<title>伟大的毅哥的框架的使用指南</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>
#text {
display: none;
}
</style>
</head>
<body>
<p id="text">{$text}</p>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!--<script src="https://cdn.bootcss.com/showdown/1.3.0/showdown.min.js"></script>-->
<script src="/showdown-1.9.0/dist/showdown.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var content = $("#text").text(); //获取md文本内容
var converter = new showdown.Converter(); //初始化转换器
var htmlcontent = converter.makeHtml(content); //将MarkDown转为html格式的内容
$("#article .article-entry").html(htmlcontent);
}); //添加到 div 中 显示出来
</script>
<div id="article">
<div class="article-entry">
</div>
</div>
</body>
</html>
前端基本告一段落
后端
controller 由 Book.php构成共有 8 个方法 其中重要的有 2个
关于遍历目录这个大家应该都能想到,就是用递归的方法。递归失败了两次,后来看到大神的代码,突然明白,感谢。
大体思路 :
匿名函数或者普通函数都可以。
需要用到的函数 file_exists()、scandir() 、is_dir()、 is_file() 、substr() 、realpath()
一个常量 DIRECTORY_SEPARATOR 在win 下为 \ 在liunx下为 / 分割路径用
。。。。。函数开始。。。。。
首先拿到路径,然后判断路径是否为空,如果为空,直接退出。
不为空的话,开始对路径进行扫描用scandir() 函数,这个函数会首先判断给出的路径是不是目录,如果不是则会直接返回 false
返回结果是一个数组,包含路径中的目录和文件。
用foreach循环出来,拼接字符串。凑成新路径
然后再用 is_dir() 判断该新路径是目录还是文件 还有就是要筛选出 . 和 .. 这在win下是返回本级目录和父目录对我们没有意义。
筛选完毕后,把 目录名 放入关联数组 title 中,而 lists 中则对 scandir() 扫描出来的内容进行 递归,判断当前路径是否还是存在。
如果is_dir() 判断出并不是目录,那我们就在判断是否为文件,因为我需要只展示md的文件,所以在这里面,我再套一个if用来判断是否是md文件(substr()),如果是才会继续记录到数组 lists 中的 title 负责记录 文件名,然后 下面的 lists 创建新的数组 以备下次递归再次调用时,建立新的数组。(因为是遵循深度优先,所以深度优先结束后,必须创建一个新的数组,让前端(代码)知道这是新的开始(新章节))
最后返回的是一个以N个一位数组开始的深度为N的N维数组。
前端就可以根据层次来编写N个foreach循环。
$getDir = function ($path) use (&$getDir) {
$lists = [];
//判断目录是否为空
if (!file_exists($path)) {
return $lists;
}
$files = scandir($path);
foreach ($files as $v) {
/**@var string $v */
$newPath = $path . DIRECTORY_SEPARATOR . $v;
if (is_dir($newPath) && $v != '.' && $v != '..') {
$lists[] = [
"title" => $v,
"lists" => $getDir($newPath)
];
} else if (is_file($newPath)) {
$namePtah = substr($newPath, -7);
if ($namePtah != 'text.md') { //用来筛选
$lists[] = [
"title" => $v,
"lists" => []
];
} else {
continue;
}
}
}
return $lists;
};
$path = realpath(__DIR__ . '/../view\Book\test');
$list = $getDir($path);
$this->assign('test', $list);
return $this->fetch();
。。。。。函数结束。。。。。
关于匿名函数,我最初用的是普通函数,带我的师傅看了之后,给我改成了匿名,然后用 use说可以加快处理速度。。。。可能吧,大佬的话咱也不敢多问。
one、one_1、one_2
然后就是展示了
用 realpath() 和 __DIR__ 拼接一个当前路径出来
用GET获取到前端的文件和文件名,然后然后拼接。
先检测是不是空,如果不是,那就开始读取 fopen()
fread()这个函数,第二个参数是控制单次读取的最大字节数,这个我感觉随意呗,1024 吉利。
$path = realpath(__DIR__ . '/../view\Book\test');
//拼接路径
if (request()->isGet()) {
$file_three = Request::Get("file_three");
$path_route = $path . "\\" . $file_three;
$file_path = $path_route;
//读取文件
if (file_exists($file_path)) {
$fp = fopen($file_path, "r");
$str = "";
$buffer = 1024;
while (!feof($fp)) {
$str .= fread($fp, $buffer);
}
$this->assign('text', $str);
return $this->fetch();
}
}
大的功能已经完成了,剩下的估计就是边边角角,没有了。
中间也是卡壳,很多东西都单独写过,但是作为一个整体,还是感觉出太嫩。继续学习。
[1] 师傅说不用one 、one_1 、one_2 这三个网页,一个网页就可以,我写到这,感觉也对,后台做点限制,用if..else走输出不同的内容就行。
最后,社畜第10天,感谢收留我的公司,还有庆祝专升本成功。啦啦啦
大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码。谢谢