Skip to content

做一个博客系统

2021-2-18 18:57:15

年前做的东西,早就想写个博客记录一下,然后就过年了。电脑充满电带回了家,一条电居然撑到了上班。事实证明mbp的电池是可以在开机状态下合盖待机11天的。

今天的课题是用php做一个静态网站生成器,也叫博客系统。

东西已经做完了,官网是 Hikari 官网,文档里边有,文档本身就是示例,所以这一个地址点进去啥都有。

如果你是在公众号阅读的这篇文章,上边的Hikari官网可能不能点击。你需要点击左下角阅读原文进入原文链接,再点链接进入官网。或者直接复制网址http://hikari.website访问。

文档写得挺详细了,这边就记录一些知识点和坑吧。第一次用php写控制台程序,有很多东西都是之前没用过的。

控制台程序

在php程序中,使用$argc获取控制台参数数量,使用$argv获取控制台参数数组。比较难受的是,就算控制台里按照选项和选项值(command -a 1 -b 2)来输入,$argv也不会给出索引数组,而是将选项也当做一个值。如果要将程序设计成需要分析选项的,就需要特别处理才能获取到选项和选项值的索引数组了。

psr4自动加载

使用composer安装类库的话,项目根目录下就会有vendor目录,我们需要在项目启动的时候引入/vendor/autoload.php,来让composer加载类库。

接口

interface规定程序模板,让实现同一个接口的类都遵循一样的模板。在Hikari中用interface规定了Cmd和Template。

php
<?php


namespace Lib\Base;


interface BaseCmd
{
    /**
     * A command line command must have a `handle` function which is public and static!
     * @return mixed
     */
    public static function handle($argv);
}

一个Cmd类必须有handle方法,这样才能根据控制台输入找到对应的Cmd类,来执行对应类的handle方法。

php
<?php


namespace Lib\Base;


interface BaseTemplate
{
    public static function render($data);
}

一个Template类必须有一个render方法,这样的设计下,将Template类放在主题的配置数组里,执行构建命令时就可以依次执行每个Template下的render方法来输出静态页了。

markdown解析

直接使用了SegmentFault/HyperDown库,可以输入markdown输出html字符串。然后在模板渲染里写样式。

模板渲染

先写了一个模板渲染方法。

php
function C($filePath, $replaceData = []) {
    if (!file_exists($filePath)) {
        return "";
    }
    $contents = file_get_contents($filePath);
    if (!empty($replaceData)) {
        foreach ($replaceData as $k => $v) {
            $contents = str_replace("{{{$k}}}", $v, $contents);
        }
    }
    return $contents;
}

然后准备了一个页面目录pages和组件目录Components,里边存带有模板语法的html片段啥的。比如首页

html
<body>
    {{navbar}}
    <div class="container">
        <img class="logo" src="/hikarilogo.png"></img>
        <h2 id="title">
            {{title}}
            <!-- <span class="version">beta 1</span> -->
        </h2>
        <h3 id="subtitle">{{subtitle}}</h3>
        <div id="menus">
            {{menu}}
            <script>
            ((function() {
                var menus = document.getElementsByClassName('menu-action')
                for (var i = 0; i < menus.length; i ++) {
                    menus[i].addEventListener('click', function() {
                        window.location.href = this.getAttribute('link')
                    })
                }
            })())
            </script>
        </div>        
    </div>
    {{footer}}
</body>

footer组件

html
<style>
    .footer {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin-top: 100px;
        color: #3E4857;
        font-size: 13px;
    }
</style>
<div class="footer">
    <div class="footer-author">
        使用 <a href="https://gitee.com/xtzero/hikari">Hikari</a> 构建
    </div>
    <div class="footer-desc">一个简洁、高效、可定制的博客框架。</div>
    <div class="footer-statistic">
        {{busuanzi}}
    </div>
    <div class="footer-police">*ICP备*号-*</div>
</div>

和不蒜子组件

html
<!-- 放在页头 -->
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<!-- 显示代码是 -->
<span id="busuanzi_container_site_pv">👁 <span id="busuanzi_value_site_pv">加载中...</span></span>

我就可以使用模板渲染方法这样渲染一个主页

php
$html = C(THEME_BASE_DIR . '/page/index.html', [
    'title' => ENV['title'],
    'subtitle' => ENV['subtitle'],
    'navbar' => C(THEME_BASE_DIR . '/components/navbar', [
        "title" => ENV['title'],
        "items" => implode("\n", array_map(function($v) {
            return C(THEME_BASE_DIR . '/components/navbarItem', $v);
        }, THEME_CONFIG['navbar']))
    ]),
    'menu' => implode("\n", array_map(function($v) {
        return C(THEME_BASE_DIR . '/components/indexNav', $v);
    }, THEME_CONFIG['homepageMenu'])),
    'footer' => C(THEME_BASE_DIR . '/components/footer', [
        "busuanzi" => C(THEME_BASE_DIR . '/components/busuanzi')
    ])
]);

要是模板能支持条件和循环渲染就好了,暂时还没做,只能用implode和array_map来代替了。

© thebestxt.cc
辽ICP备16009524号-8
本站所有文章版权所有,转载请注明出处