学习笔记——简陋的仿wiki

要求:实现类似看云的最基本功能。

大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码,骂我的技术。谢谢

语言: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天,感谢收留我的公司,还有庆祝专升本成功。啦啦啦

大佬们放过我,轻喷。可以辱骂式的提意见。但是别骂我。可以骂我代码。谢谢

猜你喜欢

转载自blog.csdn.net/github_36544258/article/details/90543102