这次是要对Typecho动刀子了,主要是为了解决误删问题。我个人对数据的存储是非常没有安全感的,特别是重要数据,我会做各种保护措施多重备份,防止出现数据丢失。

Typecho中的删除都是物理删除,虽然我会定期对整站进行备份,但误删这种事尽管你再怎么小心翼翼它都有概率会发生在你身上。如果你有良好的备份习惯倒还好,一旦你没有备份或者刚巧没有来得及备份最新版的数据那可就无力回天了。所以对于物理删除我是非常谨慎的,这次既然打算折腾那么就一次做到底,为Typecho添加逻辑删除功能。

修改之前先捋一捋Typecho的表结构及其关联关系,一共7张表,算是比较简洁了。很多内容都做了抽象处理,比如文章、页面、链接和文件等都被抽象为内容,分类和标签被抽象为项目。详细结构如下:

tabledescription
typecho_comments评论表,所有文章/页面的评论内容
typecho_contents内容表,包括文章、草稿、页面、链接、文件等类型
typecho_fields字段表,主要为内容中的自定义字段,与内容id关联
typecho_metas项目表,分类、标签、链接等
typecho_options配置表,网站的所有配置,以及插件的配置
typecho_relationships关系表,内容和项目的关联关系,如文章-标签
typecho_users用户表,网站所有的用户

重要的数据无非就是内容和评论,那么仅需要为这两张表增加逻辑删除即可。先对两张表进行修改,增加逻辑删除字段:

ALTER TABLE `typecho_contents`
ADD COLUMN `del_flag`  tinyint(4) NOT NULL DEFAULT 0 AFTER `parent`;

ALTER TABLE `typecho_comments`
ADD COLUMN `del_flag`  tinyint(4) NOT NULL DEFAULT 0 AFTER `parent`;

接着修改相关的PHP函数,先是Query.php文件,原有的物理删除函数保持不变,拓展一个逻辑删除函数,修改执行操作为UPDATE。

/**
* 删除记录操作(DELETE)
*
* @param string $table 需要删除记录的表
* @return Typecho_Db_Query
*/
public function delete($table){
    $this->_sqlPreBuild['action'] = Typecho_Db::DELETE;
    $this->_sqlPreBuild['table'] = $this->filterPrefix($table);
    return $this;
}

/**
* 逻辑删除记录操作(DELETE)
*
* @param string $table 需要删除记录的表
* @return Typecho_Db_Query
*/
public function logicDelete($table) {
    $this->_sqlPreBuild['action'] = Typecho_Db::UPDATE;
    $this->_sqlPreBuild['table'] = $this->filterPrefix($table);
    return $this;
}

接着需要将内容和评论两处的删除修改为逻辑删除函数,追加update字段参数,下为内容表的逻辑(评论表同理):

/**
 * 删除内容
 *
 * @access public
 * @param Typecho_Db_Query $condition 查询对象
 * @return integer
 */
public function delete(Typecho_Db_Query $condition){
    return $this->db->query($condition->logicDelete('table.contents')
                            ->rows(array("del_flag" => 1)));
}

另外还有几处删除内容的时候,会关联删除内容下所有的评论,如Post/Edit.php文件中的deletePost()函数中的这段:

/** 删除评论 */
$this->db->query($this->db->delete('table.comments')
                 ->where('cid = ?', $post));
// 此处需要修改为逻辑删除
$this->db->query($this->db->update('table.comments')
                 ->where('cid = ?', $post)->rows(array("del_flag" => 1)));

这样的地方一共有三处,注意同步修改。(后面在使用过程中发现有多处,注意查找)

接着就是修改查询逻辑了,需要增加逻辑删除字段筛选,以评论举例(内容同理):

/**
 * 获取查询对象
 *
 * @access public
 * @return Typecho_Db_Query
 */
public function select(){
    return $this->db->select('table.comments.coid ... more field ...')
        ->from('table.comments')->where("del_flag = ?", 0);
}

文章管理页有一个显示草稿数量的地方也需要修改:

/**
 * 获取草稿文章数目
 *
 * @access protected
 * @return integer
 */
protected function ___draftPostsNum(){
    return $this->db->fetchObject($this->db->select(array('COUNT(cid)' => 'num'))
                ->from('table.contents')
                ->where('table.contents.type = ?', 'post_draft')
                // 查询草稿数量添加删除标记逻辑
                ->where('del_flag = ?', 0))->num;
}

如此大功告成,内容和评论两张表的逻辑删除就加上了,以后再也不怕误删数据了。

Last modification:June 28th, 2020 at 10:45 am
If you think my article is useful to you, please feel free to appreciate