zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Typecho | 博客结构与插件开发笔记:附件及扩展方法

2023-06-13 09:15:30 时间

概要

最近在学习Typecho插件开发,对于Typecho博客的数据表结构和一些基础插件方法有了一定了解,这篇笔记主要记录Typecho的七大数据表之一contents表及其用于存放attachment类的数据时的一些使用心得。

数据表与插件

本文所提到的博客程序及其版本为Typecho 1.1 (17.10.30),其数据表结构在官网有较为详细的介绍,包括表的数据字典:https://docs.typecho.org/database,故在此不做赘述。但其中关于表中各属性的取值似乎并没有做举例或说明,下面对其中涉及附件功能扩充的部分属性进行举例说明补充。

contents表属性中的type与text

contens表(详细请参见官方文档)中,作者对于扩展性的考虑是相对比较周到的,其中设计的typetext两个基础属性可以对多样的内容进行扩展定义。在Typecho的设计中,博客文章、独立页面和附件(包括图片)信息都存储在contents表中,并使用type属性进行区分。原生type的取值及其对应内容类型的对应如下表所示。

type取值

对应类型

备注说明

对应text内容示例

post

文章

<!--markdown--># Hello World 如果您看到这篇文章,表示您的 blog 已经安装成功.

page

独立页面

<!--markdown-->本页面由 Typecho 创建, 这只是个测试页面.

draft

草稿

文章草稿

link

链接

不知道干啥的,作者应该打算存友情链接的

attachment

附件(含图片)

为附件元数据,不含附件自身

a:5:{s:4:”name”;s:9:”image.jpg”;}

最近经过试验探索发现,当typeattachment时,如上所示,其text中的内容存储的是附件的元数据,而这些附件的元数据是可通过插件扩充的。附件元数据默认包含的属性如下表所示。

附件元数据属性名称

说明

name

附件名称

path

附件存储相对路径

size

附件比特大小

type

附件扩展后缀名,如jpg

mime

mime类型,如image/png

利用type和text属性开发插件

以上探索可以揭示Typecho优良的可扩展性,这为开发插件增强其功能提供了帮助。下面以开发写markdown文章的刚需——图床或OSS存储插件,为例子,介绍如何利用typetext属性。

在Github调研众多大佬为Typecho开发的图床插件时,发现了gogobody开发的SmmsForTypecho,一款用于支持著名的SM.MS图床服务的Typecho插件。经过我对其1.4版本的release代码的阅读与测试发现,其对于上传到SM.MS的图片的元数据,建立了专门的数据表[prefix]smms_image_list(其中[prefix]为Typecho安装时设置的数据库表前缀,默认为typecho_)。而这个表记录的信息似乎完全是可以合并到上述contents表中的text属性中的

也就是说,我们在开发类似的图床插件时,可以利用contents表的text属性来存储图片或其他附件的信息。这可以在你的插件Plugin.php中进行实现。

我们知道,开发图床类的插件时,需要对附件上传、删除、修改和路径获取等过程进行注册,并编写自己的具体实现。下面的代码假设你已经在激活方法activate()里对上述进行了注册,并将展示如何在附件上传过程对附件添加自定义扩展元数据以及如何在路径获取过程对附件自定义扩展元数据进行读取

    // Plugin.php
    
    /**
     * 上传文件处理函数
     *
     * @access public
     * @param array $file 上传的文件
     * @return mixed
     */
    public static function uploadHandle($file)
    {
    // ...省略一堆代码...
    
    // 此方法最终要返回一个键值对array用于存入contents表的text内
    return array(
            'name' => $file['name'],  // 附件名称
            'path' => $path,      // 附件存储相对路径
            'size' => $file['size'],  // 附件比特大小
            'type' => $ext,         // 附件扩展后缀名
            'mime' => self::mimeContentType($path), // mime类型
              /* 下面是自定义的扩展元数据 */
            'hash_algo' => 'md5',   // 计算hash值所用的算法
            'hash' => hash_file('md5',$uploadFileTemp), // 附件hash值
            'url' => $data['url'],    // 附件绝对路径
            'source' => $data['url']  // 附件存储位置默认本机 loc:本机, smms:这个图床
                );
    }
    
    /**
     * 获取实际文件绝对访问路径
     *
     * @access public
     * @param array $content 单个文件的相关信息列表
     * @return string
     */
    public static function attachmentHandle(array $content)
    {
        // 此方法传入的$content就是一个contents表中的对象
        // 使用$content['attachment']->属性名 就可以访问存放在text字段中的附件元数据了
        // 根据attachment的存储位置(本地还是图床等)来获取绝对路径
        switch ($content['attachment']->source){
            case "smms":  // smms图床存储
                //存储了完整的url,这里将其相对路径摘除从而得到域名前缀,其实有点多此一举
                $domain = str_replace($content['attachment']->path,'',$content['attachment']->url);
                break;
            case "loc":   // 本机存储
            default:
                $domain = Helper::options()->siteUrl;
            break;
        }
        return Typecho_Common::url($content['attachment']->path, $domain);
    }

我利用上述代码原理,简单编写了插件并为附件添加了hash属性,用于存放上传附件的hash值,附件信息被存于数据库中时其text字段的值如下图所示。

附件存储在数据库的contents表中时的text字段(添加自定义属性'hash')