开发者社区> thinkyoung> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

typecho流程原理和插件机制浅析(第二弹)

简介: typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件机制和插件的编写方法。
+关注继续查看
  •  1 推荐
  •  14 收藏,3.7k 浏览

上一次说了 Typecho 大致的流程,今天简单说一下插件机制和插件的编写方法。

还是先上index.php

if (!@include_once 'config.inc.php') {
    file_exists('./install.php') ? header('Location: install.php') : print('Missing Config File');
    exit;
}

/** 初始化组件 */
Typecho_Widget::widget('Widget_Init');

/** 注册一个初始化插件 */
Typecho_Plugin::factory('index.php')->begin();

/** 开始路由分发 */
Typecho_Router::dispatch();

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

细心的朋友可能会发现上一次

/** 注册一个初始化插件 */
Typecho_Plugin::factory('index.php')->begin();

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

这两行代码我们并没有提起,这是为什么呢?这是因为上一期主要是分析系统执行流程,我们假设没有安装任何插件,而在没有安装插件的情况下这两行代码是没有任何作用的。

众所周知,目前大部分插件都采用钩子机制,Typecho也不例外,这两行代码就是系统在index.php里预先设定的两个插件接口,分别是整个程序流程中第一个和最后一个接口。那这种插件接口是怎么执行的呢?


我们以 HelloWorld 插件为例,HelloWorld 插件所使用的接口在 admin/menu.php,代码如下:

<?php Typecho_Plugin::factory('admin/menu.php')->navBar(); ?>

HelloWorld 插件的代码,在 usr/plugins/HelloWorld/Plugins.php :

<?php
/**
 * Hello World
 * 
 * @package HelloWorld 
 * @author qining
 * @version 1.0.0
 * @link http://typecho.org
 */
class HelloWorld_Plugin implements Typecho_Plugin_Interface
{
    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render');
    }

    /**
     * 禁用插件方法,如果禁用失败,直接抛出异常
     * 
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate(){}

    /**
     * 获取插件配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form)
    {
        /** 分类名称 */
        $name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('说点什么'));
        $form->addInput($name);
    }

    /**
     * 个人用户的配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}

    /**
     * 插件实现方法
     * 
     * @access public
     * @return void
     */
    public static function render()
    {
        echo '<span class="message success">' . Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word . '</span>';
    }
}

Typecho 在数据库 Options 表里,有一个名为 plugins 字段,里边记录了整个程序已激活插件的接口挂载情况,没有激活任何插件时 plugins 字段是这样的:

Array
(
    [activated] => Array
        (
        )

    [handles] => Array
        (
        )
)

接下来我们激活程序自带的 HelloWorld 插件看看有什么变化,激活后 plugins 字段变为:

Array
(
    [activated] => Array
        (
            [HelloWorld] => Array
                (
                    [handles] => Array
                        (
                            [admin/menu.php:navBar] => Array
                                (
                                    [0] => Array
                                        (
                                            [0] => HelloWorld_Plugin
                                            [1] => render
                                        )

                                )

                        )

                )

        )

    [handles] => Array
        (
            [admin/menu.php:navBar] => Array
                (
                    [0] => Array
                        (
                            [0] => HelloWorld_Plugin
                            [1] => render
                        )

                )

        )
)

可以看出,激活插件后,程序根据插件的激活函数

    public static function activate()
    {
        Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render');
    }

系统在数据库中将 HelloWorld 插件与 ('admin/menu.php')->navBar() 接口作了关联,
而具体关联的则是 HelloWorld_Plugin 类的 render 函数。


其实到这里大家也能看出个大概,我们访问系统后台的时候,当执行到

<?php Typecho_Plugin::factory('admin/menu.php')->navBar(); ?>

这句代码时:

  • 从数据库 plugins 字段里检索,检索到 [admin/menu.php:navBar] 下挂载了一个插件,具体为HelloWorld_Plugin 类的 render 函数,系统执行之并输出 HelloWorld 在后台的导航栏。

  • 那么如果检索不到有任何插件挂载呢,程序不执行任何动作并执行下边的代码,这也就是为什么在分析系统流程时可以直接将插件接口的代码略过的原因。


整个程序中关键的地方设置了很多类似的插件接口,方便通过编写插件而不修改程序源代码来完成我们特定的功能,设置插件接口的方法有两种:

  • 一种是 Typecho_Plugin::factory,在 var/Typecho/Plugin.php 中定义

  • 另一种是 $this->pluginHandle(), 在 var/Typecho/Widget.php 中定义

第二种是可以传递参数的接口,这个以后再说。


最后不禁有人要问,程序中设定这么多接口,即使一个插件也没安装也要挨个执行吗,效率得多低?

答案是肯定的,必须得执行,不过数据库也只读取一次,然后存在内存里,以后的每次查询都是在内存对比,多执行两行php代码基本没效率影响。具体速度咋样,用过 wp 的你懂的~~

下一节,根据具体接口,演示插件编写~

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
typecho流程原理和插件机制浅析(第一弹)
typecho流程原理和插件机制浅析(第一弹) 兜兜 393 2014年03月28日 发布 推荐 5 推荐 收藏 24 收藏,3.5k 浏览 虽然新版本0.
901 0
Egg.js使用步骤
Egg.js使用步骤
0 0
前端如何实现一键截图功能?
网页截图功能目前也是非常常见的需求, 尤其是在在线教育领域. 我们朋友圈的微信海报, 活动海报等, 一般都是运营/市场人员通过设计工具设计而成, 但是如何更好的映射到自己的服务体系里面, 比如H5页面中, 植入更多信息收集, 交互能力. 这一块的应用探索, 页面截图是一个非常好的解决方案.
0 0
SSO单点登录流程源码学习
单点登录系统无状态应用,通过对SSO单点登录系统验证码、LT存入redis,及补偿service的操作更加深入的了解单点登录系统登录流程
0 0
iOS动画开发之二——UIView动画执行的另一种方式
iOS动画开发之二——UIView动画执行的另一种方式
0 0
【laravel】第一节 访问流程
【laravel】第一节 访问流程
0 0
【52ABP实战教程】0.3-- 从github推送代码回vsts实现双向同步
需求 在之前的文章中“[DevOps]如何用VSTS持续集成到Github仓库” 我们有讲述如何将vsts中的代码编译推送到github中,这一篇我们来完善,如果有人给你开源项目推送了代码,你审核后,如何自动将代码推送回vsts,从而实现双同步。
711 0
如何删除微信web开发者工具中失效项目?
我日常使用微信web开发者工具来学习和开发我们的微信小程序,在这过程中,我们可能会创建很多小程序项目,总会有时候,我需要删除我们不需要的项目,通常情况下,我们可以进入要删除的项目,在“项目”菜单下,找到“删除项目”按钮,来将该项目与开发者工具解除绑定(代码不会真正删除)。
644 0
CHSNS#1.22开源版,演示网站同步更新至1.22
CHSNS#1.22开源版发布,演示网站同步更新至1.22 解决事件页在FF3下显示异常问题 优化载入速度及客户端运行效率 完全兼容支持.net 2.0 sp1/.net 3.5 下载:http://www.eice.com.cn/
485 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
QQ移送页面框架优化实践
立即下载
QQ移动页面框架优化实践
立即下载
函数计算最佳实践:快速开发一个分布式 Puppeteer 网页截图服务
立即下载