Typecho | 博客结构与插件开发笔记:附件及扩展方法
概要
最近在学习Typecho插件开发,对于Typecho博客的数据表结构和一些基础插件方法有了一定了解,这篇笔记主要记录Typecho的七大数据表之一contents
表及其用于存放attachment
类的数据时的一些使用心得。
数据表与插件
本文所提到的博客程序及其版本为Typecho 1.1 (17.10.30),其数据表结构在官网有较为详细的介绍,包括表的数据字典:https://docs.typecho.org/database,故在此不做赘述。但其中关于表中各属性的取值似乎并没有做举例或说明,下面对其中涉及附件功能扩充的部分属性进行举例说明补充。
contents表属性中的type与text
在contens
表(详细请参见官方文档)中,作者对于扩展性的考虑是相对比较周到的,其中设计的type
和text
两个基础属性可以对多样的内容进行扩展定义。在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”;} |
最近经过试验探索发现,当type
为attachment
时,如上所示,其text
中的内容存储的是附件的元数据,而这些附件的元数据是可通过插件扩充的。附件元数据默认包含的属性如下表所示。
附件元数据属性名称 | 说明 |
---|---|
name | 附件名称 |
path | 附件存储相对路径 |
size | 附件比特大小 |
type | 附件扩展后缀名,如jpg |
mime | mime类型,如image/png |
利用type和text属性开发插件
以上探索可以揭示Typecho优良的可扩展性,这为开发插件增强其功能提供了帮助。下面以开发写markdown文章的刚需——图床或OSS存储插件,为例子,介绍如何利用type
和text
属性。
在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
字段的值如下图所示。