要求:实现类似看云的最基本功能。
大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码,骂我的技术。谢谢
语言: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天,感谢收留我的公司,还有庆祝专升本成功。啦啦啦
大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码。谢谢