记一次wordPress博客插件开发

终于准备开始写博客了,又懒得自己再去写一个,虽然简单,但是很烦。

说实话,很早以前就知道wordPress,也知道这货就是个“臃肿”的博客系统,但是可扩展性意外的强,抱着“反正博客访问量又不会很大,臃肿点也没关系”的想法安装了WP。

装完WP过后,发现并没有地方可以设置静态生成之内的东西,顶多只有伪静态,不知道是为啥,我用动态的方式,访问首页也好,内容页也好,页面请求都要等大概1s~2s才完成(单次页面请求, 不是完整加载), 用静态的方式就完全没问题!一次请求大概30ms,便开始琢磨,去插件中心找找静态的插件。

找了一圈,着实没找到合适的,其中一个甚至有点搞笑…生成了一个html静态文件,然而却是用php去访问这个html文件再输出…那和直接动态有啥区别?就是少一次数据库请求而已。

没办法,想着自己尝试写一个插件,不过介于并没有PHP开发经验,便开始看了下官方文档,意外的发现文档很全,毕竟有其他语言的开发经验,PHP代码还是很好上手的。

好了,废话到这里结束。

1.新建结构

按照官方文档所讲的, 第一件事应该是在wp-content/plugins目录下新建一个文件夹作为插件的目录, 我这里起名叫wordpress_quick, 同时进入文件夹, 新建同名php文件wordpress_quick.php

使用IDE或者notepad++打开文件, 不推荐用记事本, 否则会有UTF-8 BOM问题, 如果刚刚新建的PHP文件是使用右键-新建文本文档的方式建立的话,最好使用notepad++打开,然后编码-使用UTF-8, 否则可能PHP会直接报错。详情请百度PHP UTF-8 BOM

开始编辑wordpress_quick.php文件, 写入最基本的插件信息

    <?php
    /*
    Plugin Name: wordpress Quick
    Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
    Description: 只针对文章页面的静态文件简单生成插件
    Version: 1.1
    Author: xiaoC
    Author URI: http://URI_Of_The_Plugin_Author作者地址
    */
    ?>

这时候就能在插件管理中看到你的插件了

2.了解WP的相关API

我这次的目的是在文章发布过后, 自动生成静态页面, 这里需要先确定几个问题

1.确定目录结构

2.确定生成时机

这里先确定目录结构, 我使用的是/article/%year%_%monthnum%_%day%/%post_id%.html, 这个在设置-固定链接里面修改, 修改完过后, 文章的URL应该为http://xiaoc.cn/article/2018_12_05/35.html这样子

如果修改完过后, 发现打开是404了, 那么说明你的主机\VPS没有配置好URL重写相关的东西, 这里以我用的IIS为例, IIS需要单独下载URL重写的安装包进行安装后才能正常使用该功能。详情百度IIS URL Rewrite

目录结构确定了, 接下来是生成的时机, 考虑了下, 至少需要在发布文章、修改文章、删除文章、评论通过、评论拒绝、评论列入垃圾列表、删除评论这几个地方重新生成或者删除缓存文件。

好在这些东西都是有相应的动作;在WP中,基本上所有的操作均会触发相应的动作、触发器,我们只需要注册相应的动作、触发器即可。

动作使用add_action进行注册,这里我们需要用到这几个动作:

publish_post (文章的发布/修改/从回收站恢复时都会触发该动作)

wp_set_comment_status(所有评论相关的操作都会触发该动作)

wp_trash_post(文章被放入回收站时,会触发该动作)

构建代码

接下来就是构建PHP代码的阶段了, 我现在写这篇文章才真正接触PHP代码第三天, 基本上是PHP 0基础,所以写的烂代码不接受任何反驳!

由于是完全静态化,所以这里根据之前确定的目录结构,先写好创建多级目录的函数

    //创建多级目录
    function mkdirs($dir, $mode = 0777){
            if (is_dir($dir) || @mkdir($dir, $mode)) return TRUE;
            if (!mkdirs(dirname($dir), $mode)) return FALSE;
            return @mkdir($dir, $mode);
    }

然后是创建一个方法,用于生成静态文件,生成的方法比较特别…

    //确定方法没有被创建
    if( !function_exists('genArticleHtml') ){
        function genArticleHtml($post_ID) {
            //这个post_ID就是文章的ID
            $date = get_post($post_ID) -> post_date; //通过ID获取发布时间, 这里为什么不直接date()呢???? 不要问我为什么, 我原本用的date("Y_m_d"),结果最后发现有时区问题,已经12月5号了,发布的文章还在2018_12_04文件夹下
            $catime = strtotime($date);
            $date = date("Y_m_d", $catime); //由于获取到的时间是时间戳,这里转换为格式化好的字符串格式
            $dirPath = WP_CONTENT_DIR . "/../article/" . $date . "/"; //WP_CONTENT_DIR即为wp-content的绝对路径,由于没有找到获取根目录路径的方法,这里就用这种方式了
            $fileName = $post_ID . ".html";
            $filePath = $dirPath . $fileName;
            mkdirs($dirPath, 0700);

            if (file_exists($filePath))unlink($filePath); //这里需要先删除已经存在的缓存文件, 否则下面请求到的永远都是缓存数据

            //接下来是生成的核心代码!!!!!
            //你没看错,这是一个URL请求!
            //我已经不想思考去构建一个页面了,所以这里直接就请求了动态的文章地址,然后直接把请求到的结果作为缓存文件!
            //我把它称为“所见即所得”
            $url= home_url() . '?p=' . $post_ID . '&time=' . date('Y_m_d');
            $html = file_get_contents($url); 

            $myfile = fopen($filePath, "w");
            fwrite($myfile, $html);
            fclose($myfile);
        }
    }

好了,生成静态文件的方法完成了,接下来就是给这个方法注册上相应的动作

    add_action('publish_post', 'genArticleHtml');

接下来就是激动人心的测试阶段,正常的话,在点击发布过后,WP根目录会自动生成article文件夹,否则你可能需要检查下权限。

剩下的就是写另外2个方法:评论发生变动后更新和删除文章后清除缓存。

这里就直接贴所有代码了,相信你也能看懂(我都看得懂你敢说看懂???)

    <?php
    /*
    Plugin Name: wordpress Quick
    Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
    Description: 只针对文章页面的静态文件简单生成插件
    Version: 1.1
    Author: xiaoC
    Author URI: http://URI_Of_The_Plugin_Author作者地址
    */

    function mkdirs($dir, $mode = 0777){
            if (is_dir($dir) || @mkdir($dir, $mode)) return TRUE;
            if (!mkdirs(dirname($dir), $mode)) return FALSE;

            return @mkdir($dir, $mode);
    }

    if( !function_exists('genArticleHtml') ){
        function genArticleHtml($post_ID) {
            $date = get_post($post_ID) -> post_date;        
            $catime = strtotime($date);
            $date = date("Y_m_d", $catime);
            $dirPath = WP_CONTENT_DIR . "/../article/" . $date . "/";
            $fileName = $post_ID . ".html";
            $filePath = $dirPath . $fileName;
            mkdirs($dirPath, 0700);

            if (file_exists($filePath))unlink($filePath);

            $url= home_url() . '?p=' . $post_ID . '&time=' . date('Y_m_d');
            $html = file_get_contents($url); 

            $myfile = fopen($filePath, "w");
            fwrite($myfile, $html);
            fclose($myfile);
        }
    }

    if( !function_exists('genArticleHtmlForCommentID') ){
        function genArticleHtmlForCommentID($comment_ID) {
            $post_ID = get_comment($comment_ID) -> comment_post_ID;     
            genArticleHtml($post_ID);
        }
    }

    if( !function_exists('delArticleHtml') ){
        function delArticleHtml($post_ID) {
            $date = get_post($id) -> post_modified;     
            $catime = strtotime($date);
            $dirPath = "../article/" . date("Y_m_d", $catime) . "/";
            $fileName = $post_ID . ".html";
            $filePath = $dirPath . $fileName;
            if (file_exists($filePath))unlink($filePath);
        }
    }

    add_action('publish_post', 'genArticleHtml'); //发布/修改/从回收站恢复时重新生成缓存
    add_action('wp_set_comment_status', 'genArticleHtmlForCommentID'); //评论发生变动时重新生成缓存
    add_action('wp_trash_post', 'delArticleHtml'); //加入回收站时删除缓存
    ?>

发表评论

电子邮件地址不会被公开。