Typecho通过插件实现构建自定义设置页

  在开发typecho主题的时候,typecho本身已经提供了封装好的设置项类,常见的例如有:CheckboxRadioSelectTextTextarea等等。我们很方便的就能通过调用相关类来添加主题设置项,这也是最常见的一种方式。虽然够用,但这也带来了一些局限性,相比较于Wordpress,灵活度还是不够高。

  为了解决上述问题,我们可以通过配合插件来从底层自己创建自定义的设置项页面。大致流程有:

  1. 通过插件添加相关路由
  2. 创建自定义的设置项表
  3. 封装相关数据库语句
  4. 创建全局变量以便于读取设置项

  下面详细叙述各个流程:

创建插件并添加路由

  创建一个插件目录,例如"YourPlugin",并在该目录下创建一个"Plugin.php"文件。接着就是添加插件基本方法以及需要继承的类,可以参考官方的HelloWorld插件来写。

  在activate()方法中,使用Helper中的addRoute添加路由:

const widgetName = 'TypechoPlugin\Furry\Router';
// 激活插件方法,如果激活失败,直接抛出异常
public static function activate()
{
    Helper::addRoute('furry_options','/furry/options', self::widgetName, 'furryOptionsPageFunc');
    Helper::addRoute('furry_options_api','/furry/api/options', self::widgetName, 'furryOptionsApiFunc');
}

  这里我添加了/furry/options以及/furry/api/options两个路由。前者用来承接设置页的路由,后者用来加载数据库中的设置项,以json形式返回给前端。

  记得在Action中实现furryOptionsPageFunc以及furryOptionsApiFunc两个方法,如果对于这一块不是很明白的可以参考Typecho的插件开发教程,网上有很多例子。这里我提供furryOptionsPageFunc的例子:

// 渲染设置页
public function furryOptionsPageFunc()
{
    if (User::alloc()->hasLogin()) {
        include_once 'options/index.php';
    } else {
        Helper::options()->response->redirect('/admin/login.php');
    }
}

  当用户登录时,访问/furry/options会加载options文件夹中的index.php。否则就会重定向到登录页面,这是一个简单的 鉴权。

创建相关数据表

  通过上面的分析,我们还知道,需要创建一张表,专门用来存放设置的数据,同样的,可以使用Typecho提供的数据库操作类来实现,对Typecho数据库Api不熟悉的可以参考我的另一篇文章: Typecho数据库常用API 。我这里给出我的例子:

// 创建设置表
private static function createFurryOptionsTable()
{
    $db = Db::get();
    $prefix = $db->getPrefix();
    $tableName = $prefix . 'furry_options';
    if (!$db->fetchRow("SHOW TABLES LIKE '$tableName'")) {
        $db->query('CREATE TABLE `' . $tableName . '` (
        `name` varchar(100) NOT NULL COMMENT \'设置名\',
        `type` varchar(20) NOT NULL COMMENT \'所属分类名\',
        `value` text COMMENT \'设置值\',
        PRIMARY KEY (`name`)
    )');
    }
}

  在插件激活时,可以调用这个方法,就会创建一张表:
lm0lxlmz.png
  包括name设置名、type所属分类名、value设置值三个字段。这样,后面我们就可以存储自己的设置项了,即使切换主题也不会丢失,因为保存在了数据库中。

初始化设置项

  表有了,下一步就是往里面写入数据。这里我们可以用一个数组来作为初始化的数据。接着用循环语句通过insert方法来插入数据,我这里举个例子:

// 初始化options数据
private static function initOptions()
{
    $arr = [
        // 全局设置
        ["type" => "global", "name" => "AuthKey", "value" => ""],
        ["type" => "global", "name" => "BuildSiteTime", "value" => ""],
        ["type" => "global", "name" => "Favicon", "value" => ""],
        ["type" => "global", "name" => "ICP", "value" => ""],
        ["type" => "global", "name" => "Police", "value" => ""],
        // 旁侧边栏
        ["type" => "sidebar", "name" => "LeftSide", "value" => "true"],
        ["type" => "sidebar", "name" => "RightSide", "value" => "true"],
    ];
    $db = Db::get();
    $prefix = $db->getPrefix();
    $tableName = $prefix . 'furry_options';
    foreach ($arr as $item) {
        $insert = $db->insert($tableName)->rows($item);
        $db->query($insert);
    }
}

  同样的,也是在插件激活的时候执行,就会得到初试的所有数据啦:
lm0mvuim.png

查询设置项并在主题中使用

  前三小节都是在插件中完成,这里,我们就需要返回主题文件夹中操作了。我们都知道,在Typecho中,themeInit函数是一个用于主题开发的钩子函数。它在每次加载主题时被调用,可以用来执行一些初始化操作和自定义功能。所以我们可以将这一步放入初始化函数中执行。也就是查询设置项并保存到全局变量中。

  在functions.php中添加下面的函数来读取设置项,并定义一个全局变量用于保存:

// 设置项全局变量
function furryThemeOptions()
{
    $db = Db::get();
    $prefix = $db->getPrefix();
    $tableName = $prefix . 'furry_options';
    $results = $db->fetchAll($db->select()->from($tableName));
    $newArray = array();
    foreach ($results as $item) {
        $newArray[$item['name']] = $item['value'];
    }
    @define('__FurryOptions__', $newArray);
}

  然后记得将这个函数在themeInit函数中调用。这样,在主题模板文件中,就可以这样使用:

<aside class="col-span-3 px-8">
    <!--加载设置项开始-->
    <?php echo __FurryOptions__['AuthKey'] ?>
    <!--加载设置项结束-->
    <?php $this->need('inc/left/left.php'); ?>
</aside>

总结

  至此,就完成了通过插件实现构建自定义设置页的教程,至于设置页的UI都可以通过自己的想法实现,甚至采用目前流行的前后端分离的方式去构建设置页。这样就能将现代前端的生态对接到typecho的管理当中。

打赏
评论区
头像
    头像

    感谢分享

    头像
    吴安歌
      

    很不错

文章目录