typecho 后台设置番外篇—数据的备份管理

因为考虑到服务器费用的问题,展开来说就是很多服务器商为了吸引用户,会给予新用户一个极低的价格,而在续费时却基本没有什么优惠,导致续费价格甚至需要在首年价格之后再添上一个0,也因此导致了一些不产生利润的站点如同候鸟一样在各大服务器商之间来回迁徙。迁移站点之前我们需要做很多工作,比如站点设置项目的数据备份。

备份后台设置项

typecho后台设置项的数据会被存储在数据库的typecho_options这张表里,字段名一般为theme:主题名,根据主题名称的不同,该字段名也会产生变化,以避免不同的主题产生字段重叠。

typecho 后台设置番外篇—数据的备份管理

设置数据的组织结构如下图,看起来是不是有点象一组json数据?主题设置项目较多的时候,手动重设会耗费一定的时间。当需要给站点搬家的时候,我们还是希望能够拿到一份备份的文件,以便在需要的时候直接导入。

typecho 后台设置番外篇—数据的备份管理

代码实现

在主题设置页添加了一个表单,以实现数据备份与下载的功能,使用input元素提交的时候没有什么问题,但修改为button元素后,表单数据就无法正确被提交了,最后只能利用js给按钮分别做了绑定,当按钮被点击后,先去修改隐藏的input的value,再执行表单提交操作。

<?php
$name = "august";
$db = Typecho_Db::get();
$backupDir = AUG_THEME_DIR . '/backup/';
if (isset($_POST['type'])) {
    $value = $db->fetchRow($db->select()->from('table.options')->where('name = ?', 'theme:' . $name))['value'];

    if ($_POST["type"] == "backup") {
        $backupData = [
            'backup_time' => date('Y-m-d H:i:s'),
            'theme' => $name,
            'settings' => unserialize($value)
        ];
        $jsonData = json_encode($backupData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
        $filename = $backupDir . 'theme_' . $name . '_backup.json';
        if (file_put_contents($filename, $jsonData)) {
            ?>
            <script>alert("设置已成功备份!");</script>
            <?php
        } else {
            ?>
            <script>alert("备份失败,请检查backup目录权限!");</script>
            <?php
        }
    }
    
    if ($_POST["type"] == "recovery") {
        $backupFile = $backupDir . 'theme_' . $name . '_backup.json';
        if (file_exists($backupFile)) {
            $backupContent = file_get_contents($backupFile);
            $backupData = json_decode($backupContent, true);
            if ($backupData && isset($backupData['settings'])) {
                $serializedSettings = serialize($backupData['settings']);
                $db->query($db->update('table.options')->rows(array('value' => $serializedSettings))->where('name = ?', 'theme:' . $name));
                ?>
                <script>
                    alert("已从备份文件恢复设置!");
                    window.location.href="<?php Helper::options()->adminUrl('options-theme.php');?>";
                </script>
                <?php
            } else {
                ?>
                <script>
                    alert("备份文件解析失败,可能已损坏!");
                </script>
                <?php
            }
        } else {
            ?>
            <script>
                alert("未找到备份文件,无法恢复!");
            </script>
            <?php
        }
    }
    
if ($_POST["type"] == "download") {
    $backupFile = $backupDir . 'theme_' . $name . '_backup.json';
    ob_clean();
    ob_start();
    if (file_exists($backupFile)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="theme_' . $name . '_backup.json"');
        header('Content-Length: ' . filesize($backupFile));
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        ob_end_flush();
        readfile($backupFile);
        exit;
    } else {
        ?>
        <script>
            alert("没有找到可下载的备份文件!"); 
        </script>
        exit;
        <?php
    }
}
}

?>
<form id="backup" class="backup" action="" method="post">
    <input type="hidden" name="type" value="">
    <button type="button" value="backup" class="icon-btn">
        <i class="fa fa-save"></i>
    </button>
    <button type="button" value="recovery" class="icon-btn">
        <i class="fa fa-undo"></i>
    </button>
    <button type="button" value="download" class="icon-btn">
        <i class="fa fa-download"></i>
    </button>
</form>

按钮动作绑定的js代码:

    document.querySelectorAll('#backup button[type="button"]').forEach(btn => {
        btn.addEventListener('click', function(e) {
            e.preventDefault();
            const form = this.closest('form');
            const hiddenInput = form.querySelector('input[name="type"]');
            hiddenInput.value = this.value;
            form.submit();
        });
    });

标签: typecho

移动端可扫我直达哦~

推荐阅读

thumbnail 2025-06-08

typecho前台ajax登录与错误处理

尝试了在主题前台做一个登录框,登陆的功能是实现了,有一个小小的不便,就是如果输错了密码,因为页面又跳回了首页,所以弹出式登录框又被隐藏了,登录成功与否不够明显,二次登录的场合操作也较繁琐,所以想实现前台以ajax的方式登录。实现aja...

建站相关 typecho

thumbnail 2025-06-08

聊聊html里的head部分

HTML文档的<head>部分是一个容器,用于包含文档的元数据(metadata)和链接到外部资源的信息,这些内容不会直接显示在网页上,但对网页的功能和表现至关重要。主要元素和功能1. 基础元素<title>:...

建站相关 typecho

thumbnail 2025-06-04

typecho前端实现站点语言的切换

前端修改的数据能及时反馈到后端,那当然需要一个前后端都可以无障碍读取的东西,所以最初是想要用localstorage,但发现php无法直接读取其值,所以就换成了cookie。前端通过js来设置参数值:document.cookie='...

建站相关 typecho

thumbnail 2025-06-02

typecho 主题中的模板与模块的概念

模板是 typecho 主题中一个重要的概念,我们说过typecho的极简主题可以只存在 index.php 这一个文件,但需要展现分类页的时候,typecho事实上会先去寻找名为 category.php 的分类页模板,文章页当然也...

建站相关 typecho

thumbnail 2025-06-02

typecho的几种常见的文章列表调用

处理好了header与面包屑,接下来就按照自己的需求自由发挥了,先放一个分类列表,再挑出一个喜欢的标签,自定义一个该标签下内容展示模块。Typecho 提供了多种文章循环方式,以下是常用的几种方法:标准文章循环<?php whi...

建站相关 typecho

thumbnail 2025-06-02

在typecho里实现面包屑导航

什么是面包屑导航面包屑导航是一种网站导航方式,通常在网站顶部显示,大多会放在站点header的下方,用于显示用户当前位置。 面包屑导航由导航元素构成,每个元素代表一个网站导航项,各个元素通常包含对应链接,供用户跳转。面包屑导航示例首页...

建站相关 typecho

thumbnail 2025-05-29

关于typecho中的路由知识

路由(Routing)是博客系统中将URL地址映射到具体处理逻辑的机制,它决定了当用户访问某个网址时,系统应该执行什么操作、显示什么内容。typecho站点一般都会开启伪静态,伪静态通过URL重写将"漂亮"的URL映射到实际的文件路径...

建站相关 typecho

thumbnail 2025-05-29

Typecho 模板中的翻译函数 _t 与 _e

在 Typecho 模板开发中,_t 和 _e 是用于国际化处理的函数,核心区别在于输出方式:"_t" 函数‌‌功能‌:获取翻译后的字符串但不直接输出,需结合 echo 使用。‌示例‌:<?php echo _t('欢迎语');...

建站相关 typecho

thumbnail 2025-05-26

typecho文章自定义字段的删除与修改

涉及数据库的操作,务必请提前做好备份!提前做好备份!!做好备份!!!小鸟数据的当前主题的缩略图字段命名为augPostThumb,这几天在尝试完善一下原有主题,下载了原站的数据库导入了测试站用于测试页面效果,测试主题的缩略图相关字段拟...

建站相关 typecho

thumbnail 2025-05-26

typecho的文章自定义字段的知识笔记

在typecho中,除了可以自定义设置项之外,我们也可以给文章自定义一些额外的字段,比如给文章编辑界面添加一个缩略图选项,或者增加一个keywords输入框,用来修改编辑当前内容页的关键词信息。// 主题设置 function th...

建站相关 typecho