wetypecho服务端插件代码分析

引言

我在很久之前就想研究这个项目,然后再进行些自定义的修改了。就以本文作为笔记开始吧。

WeTypecho 把 Typecho 博客和微信小程序用户打通:登录、点赞、阅读量、后台看用户。先看清目录和激活时改了数据库什么,再动 Action.php 接口会轻松很多。

项目目录树

.
├── Action.php
├── Plugin.php
├── Users.php
├── res //一些图片资源
│   ├── cvbg.jpeg
│   ├── cvborder.jpeg
│   ├── resend.png
│   └── test.bin
├── sql // 创建了两个数据库
│   ├── wetypecho.sql
│   └── wetypecholike.sql
└── tree.txt

Action.php 处理 API 请求,Plugin.php 负责启停和挂钩,Users.php 是后台用户面板;sql/ 里是建表脚本,激活时按前缀执行。

查看数据库结构

wetypecho.sql

CREATE TABLE `typecho_wetypecho` (
  `id`                int(10) unsigned NOT NULL auto_increment,
  `openid`            varchar(255)     default ''  ,
  `createtime`        int(10)          default 0   ,
  `lastlogin`         int(10)          default 0   ,
  `nickname`          varchar(255)     default ''  ,
  `avatarUrl`         varchar(255)      default ''  ,
  `city`              varchar(255)      default ''  ,
  `country`           varchar(255)      default ''  ,
  `gender`            varchar(255)      default ''  ,
  `province`          varchar(255)     default ''  ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

看内容可以推测,这是微信用户数据表。

openid 是微信侧唯一标识;createtime / lastlogin 用 int 时间戳,和 Typecho 其它表风格一致。

wetypecholike.sql

CREATE TABLE `typecho_wetypecholike` (
  `id`                int(10) unsigned NOT NULL auto_increment,
  `openid`            varchar(255)     default ''  ,
  `cid`               int(10)          default 0   ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这应该是个微信点赞表

(openid, cid) 业务上应唯一,脚本里只有自增 id,高并发点赞可能要自己加唯一索引防重复。

php代码分析

激活进行的初始化操作代码

启用插件时依次:注册路由 /api/[type]、挂后台面板、在文章渲染前插 view_count、建两张表、给 contents / comments 加扩展字段。

Helper::addRoute('jsonp', '/api/[type]', 'WeTypecho_Action');

        Helper::addAction('json', 'WeTypecho_Action');

        Helper::removePanel(1, 'WeTypecho/users.php');

        Helper::addPanel(1, 'WeTypecho/Users.php', 'WeTypecho', '我的用户', 'administrator');

        $db = Typecho_Db::get();

        $prefix = $db->getPrefix();

        Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('WeTypecho_Plugin','view_count');

        //创建用户数据库

        $scripts = file_get_contents('usr/plugins/WeTypecho/sql/wetypecho.sql');

        $scripts = str_replace('typecho_', $prefix, $scripts);

        $scripts = explode(';', $scripts);

        try {

            if (!$db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}wetypecho';", Typecho_Db::READ))) {

                foreach ($scripts as $script) {

                    $script = trim($script);

                    if ($script) {

                        $db->query($script, Typecho_Db::WRITE);

                    }

                }

            }

        } catch (Typecho_Db_Exception $e) {

            throw new Typecho_Plugin_Exception(_t('数据表建立失败,插件启用失败,错误信息:%s。', $e->getMessage()));

        } catch (Exception $e) {

            throw new Typecho_Plugin_Exception($e->getMessage());

        }

        //创建赞数据库

        $scriptslike = file_get_contents('usr/plugins/WeTypecho/sql/wetypecholike.sql');

        $scriptslike = str_replace('typecho_', $prefix, $scriptslike);

        $scriptslike = explode(';', $scriptslike);

        try {

            if (!$db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}wetypecholike';", Typecho_Db::READ))) {

                foreach ($scriptslike as $script) {

                    $script = trim($script);

                    if ($script) {

                        $db->query($script, Typecho_Db::WRITE);

                    }

                }

            }

        } catch (Typecho_Db_Exception $e) {

            throw new Typecho_Plugin_Exception(_t('数据表建立失败,插件启用失败,错误信息:%s。', $e->getMessage()));

        } catch (Exception $e) {

            throw new Typecho_Plugin_Exception($e->getMessage());

        }

        //创建赞数据库

        try {

            //增加点赞和阅读量

            if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents'))))

            {

                $db->query(

                    'ALTER TABLE `' . $prefix

                    . 'contents` ADD `views` INT DEFAULT 0;'

                );

            }

            if (!array_key_exists('likes', $db->fetchRow($db->select()->from('table.contents'))))

            {

                $db->query(

                    'ALTER TABLE `' . $prefix

                    . 'contents` ADD `likes` INT DEFAULT 0;'

                );

            }

            if (!array_key_exists('authorImg', $db->fetchRow($db->select()->from('table.comments'))))

            {

                $db->query(

                    'ALTER TABLE `' . $prefix

                    . 'comments` ADD `authorImg` varchar(500) DEFAULT NULL;'

                );

            }

        } catch (Exception $e) {

            echo($e->getMessage());

        }

Helper::addRoute / addAction 把 JSON API 暴露出去;removePaneladdPanel 是把自带面板换成插件自己的 Users.php。建表前 SHOW TABLES LIKE 避免重复执行;str_replace('typecho_', $prefix) 适配不同表前缀。ALTER TABLEcontentsviewslikes,给 commentsauthorImg,失败时只 echo 异常,生产环境建议写日志。后续读 WeTypecho_Action 可看具体 type 参数对应登录还是点赞。

版权声明: 本文首发于 指尖魔法屋-wetypecho服务端插件代码分析https://blog.thinkmoon.cn/post/250-source-code-wetypecho-php-typecho/) 转载或引用必须申明原指尖魔法屋来源及源地址!