Typecho是一个轻量级的博客程序,在使用过程中难免会有功能是没有的,正所谓萝卜青菜各有所好,要实现自己想要的功能但又不能破坏程序本有的代码结构,那就需要制作成插件了。

制作的插件需要一个接口,才可以使之嵌入到博客程序当中,要实现的功能才会生效,接下来通过转载木然轩的一篇插件开发教程简单说明typecho插件的制作方法:

给插件取个名字,假设叫LoginBeautify吧,名字注意不能有_。然后在Typecho的插件目录创建一个和插件名一致的文件夹(也就是LoginBeautify),在新建的这个文件夹下创建文件Plugin.php。这个是Typecho的约定,Typecho会自动扫描插件目录,解析目录下的Plugin.php

Plugin.php内键入以下内容,主要是插件的描述信息,填写一下就行:

一、创建插件

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * 登录界面美化
 *
 * @package LoginBeautify
 * @author jlice
 * @version 1.0.0
 * @link https://jlice.top
 */
class LoginBeautify_Plugin implements Typecho_Plugin_Interface
{
}

这里需要注意:插件必须以class 插件名_Plugin implements Typecho_Plugin_Interface{插件内容}的方式实现,所有的代码都必须包含在这个大括号之内。

二、插件的配置

1.activatedeactivate分别是启用和禁用插件时运行的代码。
2.configpersonalConfig分别是插件的后台配置面板和后台个人设置面板。

需要注意的是,上面这些方法都是静态的(有static修饰),粗糙点说就是不能用$this

什么是接口点?

这里我称之为:“接口点”(原文叫钩子),假如Typecho的作者觉得某个地方可以交给插件去完成,可以在这个地方放一个接口点,然后插件挂载到这个接口点上,程序在运行时,会检查接口点有没有挂载插件,如果有会执行插件的代码。
通过上面的理解,我们可以知道,插件要声明注册到哪个接口点,执行什么代码,这样Typecho才能知道何时执行以及执行什么代码。当然,一个插件也可以挂载到多个接口点。实际上,Typecho在启用或禁用插件时就会把插件的数据保存到数据库,位于options表里。

Typecho预留的接口点是以 Typecho_Plugin::factory()->function(); 的方法实现的。
如果要看所有的钩子,可以参考官方文档,或者在代码里搜索。这里我推荐 sublime text 3 一个代码编辑器,可以搜索文件夹中文件里面的代码。
例如:

Searching 233 files for "Typecho_Plugin::factory"

C:\Users\said\Desktop\32214344\build\admin\common.php:
   16  
   17  /** 注册一个初始化插件 */
   18: Typecho_Plugin::factory('admin/common.php')->begin();
   19  
   20  Typecho_Widget::widget('Widget_Options')->to($options);

C:\Users\said\Desktop\32214344\build\admin\editor-js.php:
  108      });
  109  
  110:     <?php Typecho_Plugin::factory('admin/editor-js.php')->markdownEditor($content); ?>
  111  
  112      var th = textarea.height(), ph = preview.height(),

C:\Users\said\Desktop\32214344\build\admin\footer.php:
    4  <?php
    5  /** 注册一个结束插件 */
    6: Typecho_Plugin::factory('admin/footer.php')->end();
    7  

C:\Users\said\Desktop\32214344\build\admin\header.php:
   13  
   14  /** 注册一个初始化插件 */
   15: $header = Typecho_Plugin::factory('admin/header.php')->header($header);
   16  
   17  ?><!DOCTYPE HTML>

找到合适的接口点

接口点那么多,怎么能知道哪个接口点符合自己的需求呢?这个问题,em...,其实不太好回答。
我们注意到两个目录:一个是var/Widget/,这里是Typecho的核心代码,里面有Typecho定义的各种Widget;另一个是admin/,这里是后台管理的代码。
Widget是组件的意思,例如Widget_Archive就是输出文章的,例如首页和文章页面。Widget里的接口点可以定制这些组件的行为。具体有哪些组件可以参考官方文档,或者直接看var/Widget/这个目录就可以了。
接口点的位置有两个层面的意思,或者说为了指定要挂载哪个接口点,我们需要确定两件事:一是这个接口点在哪,对于admin/下的,需要指定.php文件位置,对于var/Widget/里的接口点,只需要指明类名即可(也就是Widget的名字);二是这个接口点的名字,也就是function的名字。

下面是一些例子:

// var/Widget/Upload.php
$result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasUploaded)->uploadHandle($file);
// Widget: Widget_Upload    function: uploadHandle

// var/Widget/Contents/Post/Edit.php
$this->pluginHandle()->finishPublish($contents, $this);
// Widget: Widget_Contents_Post_Edit    function: finishPublish

// admin/write-js.php
Typecho_Plugin::factory('admin/write-js.php')->write();
// php: admin/write-js.php    function: write

p.s.需要注意的是第一个例子里的trigger并不是钩子的名字,这个是Typecho用来判断是否有插件挂载到这里用的。

由于我们要做登录界面美化,也就是改登录界面背景,很自然地想到后台管理的登录界面,也就是admin/login.php,虽然我们在这个文件里并没有发现接口点,但在它的引入文件footer.php却发现了:

/** 注册一个结束插件 */
Typecho_Plugin::factory('admin/footer.php')->end();

p.s. 在看文件的时候我们不要把include给忽略了,这好比把一个文件分割成了几个文件,这是php的基本知识。

于是,我们的LoginBeautify插件找到了它的接口点:

启用插件

public static function activate()
{
    Typecho_Plugin::factory('admin/footer.php')->end = array('LoginBeautify_Plugin', 'end');
}

把整个插件内容做为一个集合添加到这个接口点里去,end是一个函数,下面会继续写它的内容。

禁用插件

public static function deactivate(){}
有些插件禁用虽然回收一些东西,但我们这里没有,所以括号内留空。

插件配置面板

public static function config(Typecho_Widget_Helper_Form $form)
{
    $url = new Typecho_Widget_Helper_Form_Element_Text('bgUrl', NULL,'','未登录背景', _t("背景URL"));
    $form->addInput($url);
}
``
这里的意思是在启用插件后,在设置里添加一个text文本框,分别是:文本框名,选择项,默认值,标题,说明。

个人设置
`public static function personalConfig(Typecho_Widget_Helper_Form $form){}`
不需要,留空。

###函数end内容编写###
要写什么内容就要看我们要实现什么样的功能了,这里我们要实现一个基本功能,判断用户有没有登录,没有就添加背景图片。

由于`end`没有输入参数,所以我们这里增加的`end`方法也没有输入参数。如果钩子有输入参数,我们对应增加的方法里应该有对应的输入参数。

我们注意到`login.php`的最开始有如下代码:

<?php
include 'common.php';

if ($user->hasLogin()) {

$response->redirect($options->adminUrl);

}

这几行代码的意思是:引入`common.php`,如果用户已经登录了,就跳转到管理地址。可是,`$user`、`$response`和`$options`这些变量哪来的呢?
查看`common.php`。可以发现如下代码:

Typecho_Widget::widget('Widget_Options')->to($options);
Typecho_Widget::widget('Widget_User')->to($user);
Typecho_Widget::widget('Widget_Security')->to($security);
Typecho_Widget::widget('Widget_Menu')->to($menu);

`Typecho_Widget::widget`是一个工厂方法,可以返回类的实例。`to()`方法可以把这个实例赋值给某个变量。

因此,在我们的插件里页可以采用类似的做法:

public static function end()
{

Typecho_Widget::widget('Widget_User')->to($user);
//把设置里的bgUrl值附给$url
$url = Typecho_Widget::widget('Widget_Options')->plugin('LoginBeautify')->bgUrl;
if (!$user->hasLogin()) {
    echo '<script>$("body").css("background", "url(' .  $url . ')");</script>';
}

}

这里,我们通过`jQuery`代码来修改页面背景的,这样整个插件代码就写完了。

#完整代码#:

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**

  • 登录界面美化
    *
  • @package LoginBeautify
  • @author jlice
  • @version 1.0.0
  • @link https://jlice.top
    */

class LoginBeautify_Plugin implements Typecho_Plugin_Interface
{

public static function activate()
{
    Typecho_Plugin::factory('admin/footer.php')->end = array('LoginBeautify_Plugin', 'end');
}

public static function deactivate() {}

public static function config(Typecho_Widget_Helper_Form $form)
{
    $url = new Typecho_Widget_Helper_Form_Element_Text(_t('bgUrl'), NULL, NULL, _t("背景URL"));
    $form->addInput($url);
}

public static function personalConfig(Typecho_Widget_Helper_Form $form) {}

public static function end()
{
    Typecho_Widget::widget('Widget_User')->to($user);
    $url = Typecho_Widget::widget('Widget_Options')->plugin('LoginBeautify')->bgUrl;
    if (!$user->hasLogin()) {
        echo '<script>$("body").css("background", "url(' .  $url . ')");</script>';
    }
}

}

本文主要内容转自[木然轩][1],这只是一个基本插件的教程,有了这个基础可以查看其它人写的插件代码,像我这种不懂PHP的人都能看明白大部分^_^

看代码还得有好工具,虽然宝塔面板后台看也不麻烦,但免不了有时本地需要,推荐sublime text 3这个工具,免安装,和宝塔后台看的代码高亮一个样。