ECJiaWiki:如何快速创建一个插件

来自ECJiaWiki
跳转至: 导航搜索

目录

第一篇:通用插件入门

1、什么是插件?插件能做什么?

插件是一种外挂于主应用的程序,具有可扩展性,不能独立与主应用运行。

插件层是EC+的业务的扩展,根据业务的不同场景下的需求不同,可以轻松通过插件对应用的扩展进行业务逻辑补充。后台可轻易安装、卸载、移除插件。

2、插件位置

插件存放在 plugins 目录下,新建插件需要在这个目录下进行创建。

Daojia plugins 1.png

3、插件种类介绍?

有system、captcha、cron、platform、payment、shipping、sms、connect八大类:

类型名 类型前缀 简单描述 示例
system 系统 calculator(计算器)
captcha captcha 验证码 captcha_royalcms(ROYALCMS验证码)
cron cron 计划任务 cron_bill_day(商家结算帐单按日生成)
platform mp 公众平台 mp_dzp(大转盘)
payment pay 支付方式 pay_alipay(支付宝)
sms sms 短信 sms_alidayu(阿里大于短信)
shipping ship 配送方式 ship_sf_express(顺丰速运)
connect sns 第三方登陆 sns_qq(QQ帐号登录)

Daojia plugins 2.jpg

4、插件目录命名规范

插件目录命名规范:插件类型前缀 + 插件名

举例子:新建一个微信公众平台插件,插件名为 test

plugins 目录下新建 mp_test 目录:

Daojia plugins 3.png

5、如何定义插件

定义一个插件需要为插件新建一个插件入口主文件,并必须遵循插件定义规范,插件入口主文件是处理插件定义、注册、安装、卸载等最基本功能的文件,必须有。

举例子:定义 test 微信公众平台插件:

  1. mp_test 目录下新建一个 mp_test.php

    命名规范:插件类型前缀_ + 插件名.php

    Daojia plugins 4.png

  2. (重点)插件描述信息是通过注释来定义的,下面为范例(注释不可或缺):

    <?php
    
    /*
    Plugin Name: 测试插件
    Plugin URI: http://www.ecjia.com/plugins/ecjia.mp_tests/
    Description: 用于测试的插件。
    Author: ECJIA TEAM
    Version: 1.18.0
    Author URI: http://www.ecjia.com/
    Plugin App: platform
    */
    
    // 代码省略
    // 。。。
    
    • Plugin Name:插件名称

    • Plugin URI:插件URL

    • Description:插件描述

    • Author:开发者

    • Version:版本号

    • Author URI:开发者地址

    • Plugin App:插件类型(必须指定一种插件种类,未指定无法使用插件)

  3. 在注释的下面新建一个类,类的命名必须遵守规范,里面的方法格式不建议改动:

    类的命名规范: plugin_ + 插件目录名

    下面为范例:

    //类名:plugin_mp_test
    class plugin_mp_test {
        
    	//安装插件方法
    	public static function install() {
            // 定义配置文件
    		$config = include(RC_Plugin::plugin_dir_path(__FILE__) . 'config.php');
    		$param = array('file' => __FILE__, 'config' => $config);
    	return RC_Api::api('platform', 'plugin_install', $param);
    	}
        
    	//卸载插件方法
    	public static function uninstall() {
            // 定义配置文件
    		$config = include(RC_Plugin::plugin_dir_path(__FILE__) . 'config.php');
    		$param = array('file' => __FILE__, 'config' => $config);
    		return RC_Api::api('platform', 'plugin_uninstall', $param);
    	}
    }
    

6、插件注册、安装、卸载

  1. 在之前定义的类下面,添加一个继承方法来定义一个用于注册插件的文件:

    需要注意继承的值为插件目录名 ,返回值也是 插件目录名 ,这里定义mp_test.class.php 为管理该插件的文件(后面章节会介绍管理插件文件的作用和开发方法)

    Ecjia_PluginManager::extend('mp_test', function() {
        require_once RC_Plugin::plugin_dir_path(__FILE__) . 'mp_test.class.php';
        return new mp_test();
    });
    
  2. 在继承方法下添加安装和卸载的方法:

    需要注意注册的值为 plugin_ + 插件目录名

    // 注册 test 微信公众平台插件
    RC_Plugin::register_activation_hook(__FILE__, array('plugin_mp_test', 'install'));
    // 卸载 test 微信公众平台插件
    RC_Plugin::register_deactivation_hook(__FILE__, array('plugin_mp_test', 'uninstall'));
    

7、插件配置文件介绍

每个插件的配置文件内容的项都是不同的,下面以微信公众平台插件为例:

在该插件根目录下新建一个config.php 文件

ECJia plugins 32.png

<?php
defined('IN_ECJIA') or exit('No permission resources.');
/**
 * 微信公众平台配置菜单
 */
return array(
    // 插件名称
    'ext_code'              => 'mp_test',
    
     // 插件图标
    'ext_icon'              => 'images/icon_goods.png',

    // 默认关键字
    'commands'              => ['test', '测试'], 

    // 子命令
    'sub_code'              => ['subfoo' ],
    
    //仅支持微信公众平台
    'support_platform'      => 'wechat', 

    // 支持微信所有类型公众号
    'support_platform_type' => ['service', 'unauthorized', 'subscribe', 'test'],
    
    // 支持商家和平台
    'support_type'  => Ecjia\App\Platform\Plugin\PlatformAbstract::TypeAdmin | Ecjia\App\Platform\Plugin\PlatformAbstract::TypeMerchant,

    // 表单配置项			
    'forms' => array(
    ),
);

// end

参数说明

  • ext_code:插件名称,必须和插件目录一致
  • ext_icon:插件图标,插件目录相对路径)
  • commands:默认关键字。
  • sub_code:子命令。
  • support_platform:支持微信公众平台
  • support_platform_type:支持微信公众号类型,可多选
  • support_type:支持商家或平台
  • forms:表单配置项(可选,可为空)

8、插件配置表单定义和验证、获取值

表单定义

编辑 config.php 配置文件,添加或修改 forms 字段

<?php
defined('IN_ECJIA') or exit('No permission resources.');

return array(
    // ......
    // 上省略

    'forms' => array(
		array('name' => 'test_value',       'type' => 'text',    'value' => ''),
		array('name' => 'test_radio',       'type' => 'radio',    'value' => ''),
    ),
    
    // 下省略
    // ......
);

// end

参数说明

  • name:配置项名称
  • type:配置项类型(表单类型)
    • text: 文本域
    • password: 密码字段
    • radio: 单选按钮
    • checkbox: 复选框
    • textarea: 文本域
    • select: 下拉选项列表
  • value:配置项默认值,注意:radio和checkbox无效。

要设置radiocheckbox的值,需要编辑语言包文件:

  1. 在插件目录下新建languages文件夹
  2. languages文件夹下新建zh_CN文件夹
  3. zh_CN文件夹下新建一个plugin.lang.php文件(默认语言包文件,不建议修改文件名)。

ECJia plugins 27.png

<?php
/**
 * 测试语言文件
 */
defined('IN_ECJIA') or exit('No permission resources.');

return array(

      // 将表单 name 'test_value' 本地化为‘测试文本框:’
      'test_value' => '测试文本框:',

      // 将表单 name 'test_radio' 本地化为‘测试单选:’
      'test_radio' => '测试单选:',


      'test_radio_range'  => array(
          // '表单值' => '显示值'
          '86400' => '24小时',
          '3600' => '1小时',
          '60' => '1分钟',
      ),
 );

表单获取

只需要一句话即可获取,以下为范例:

获取配置文件的test_value的值

// 获取配置文件的test_value的值,存到$test_value变量
$test_value = $this->getConfig('test_value');

第二篇:公众平台插件开发

1、插件主类继承对象和实现方法

目录下新建一个 mp_test.class.php 文件,必须实现以下方法。

Daojia plugins 13.png

<?php
 /**
 * 微信测试
 */
defined('IN_ECJIA') or exit('No permission resources.');

// 新建mp_test类继承PlatformAbstract
class mp_test extends PlatformAbstract
{
     /**
     * 获取插件代号
     * 
     * @see \Ecjia\System\Plugin\PluginInterface::getCode()
     */
    public function getCode()
    {
    	// 获取插件代号值应插件种类而异,微信公众平台插件代号为"ext_code"
        return $this->loadConfig('ext_code');
    }
    
    /**
     * 加载配置文件
     *
     * @see \Ecjia\System\Plugin\PluginInterface::loadConfig()
     */
    public function loadConfig($key = null, $default = null)
    {
    	// 加载"config.php"配置文件
        return $this->loadPluginData(RC_Plugin::plugin_dir_path(__FILE__) . 'config.php', $key, $default);
    }

    /**
     * 加载语言包
     *
     * @see \Ecjia\System\Plugin\PluginInterface::loadLanguage()
     */
    public function loadLanguage($key = null, $default = null)
    {
        $locale = RC_Config::get('system.locale');

        return $this->loadPluginData(RC_Plugin::plugin_dir_path(__FILE__) . '/languages/'.$locale.'/plugin.lang.php', $key, $default);
    }
    
    
    /**
     * 获取iconUrl
     * {@inheritDoc}
     * @see \Ecjia\App\Platform\Plugin\PlatformAbstract::getPluginIconUrl()
     */
    public function getPluginIconUrl()
    {

    	// 获取iconUrl值因插件类型而异,部分插件没有图标,微信公众平台插件图标iconUrl为"ext_icon"
        if ($this->loadConfig('ext_icon')) {
            return RC_Plugin::plugin_dir_url(__FILE__) . $this->loadConfig('ext_icon');
        }
        return '';
    }

    /**
     * 事件回复
     * 注意:微信公众平台特有方法,用于事件回复,并且事件回复的出口必须写在这里。
     * {@inheritDoc}
     * @see \Ecjia\App\Platform\Plugin\PlatformAbstract::eventReply()
     */
    public function eventReply() {
        // 回复数据
        $articles = array(
            // 图文信息标题
            'Title'         => '测试插件',
            // 图文信息正文
            'Description'   => '这是一个测试插件',
            // 点击图文详细后跳转的链接
            'Url'           => '',
            // 图文信息图片(获取images文件下wechat_thumb_pic_success.png图片)
            'PicUrl'        => RC_Plugin::plugin_dir_url(__FILE__) . '/images/wechat_thumb_pic_success.png',
        );

        return WechatRecord::News_reply($this->getMessage(), $articles['Title'], $articles['Description'], $articles['Url'], $articles['PicUrl']);
    }
}

特别注意

  • getCode方法获取插件代号值应插件种类而异,微信公众平台插件代号为"ext_code"
  • getPluginIconUrl方法获取iconUrl值因插件类型而异,部分插件没有图标,微信公众平台插件图标iconUrl为"ext_icon"
  • eventReply方法为微信公众平台特有方法,用于事件回复,并且事件回复的出口必须写在这里。

2、公众平台插件回复内容

  1. 编辑插件管理配置文件 mp_test.class.php ,
  2. 编辑 eventReply 方法,
  3. 关键字回复有多种方式,下面是例子是图文消息回复

ECJia plugins 14.png

/**
 * 事件回复
 * {@inheritDoc}
 * @see \Ecjia\App\Platform\Plugin\PlatformAbstract::eventReply()
 */
public function eventReply() {

    // 回复数据
    $articles = array(
        // 图文信息标题
        'Title'         => '测试插件',
        // 图文信息正文
        'Description'   => '这是一个测试插件',
        // 点击图文详细后跳转的链接
        'Url'           => '',
        // 图文信息图片(获取images文件下wechat_thumb_pic_success.png图片)
        'PicUrl'        => RC_Plugin::plugin_dir_url(__FILE__) . '/images/wechat_thumb_pic_success.png',
    );

    return WechatRecord::News_reply($this->getMessage(), $articles['Title'], $articles['Description'], $articles['Url'], $articles['PicUrl']);
}

3、插件安装

平台后台点击 控制面板 ,然后点击 插件管理

Daojia plugins 7.png

这时候找到制作的插件,点击 安装

Daojia plugins 8.png

如果一切顺利,可以看到:

Daojia plugins 9.png

4、插件开通关闭

进入公众平台管理界面,点击插件管理,这时候看到了我们在下方插件库看到了测试插件:

ECJia plugins 18.png

点击测试插件,点击开通二次确认后即可开通

ECJia plugins 19.png

如果一切顺利,这时候返回插件库,可以看到提示已经安装了

ECJia plugins 20.png

停止反之,点击测试插件,点击关闭二次确认后即可关闭,

ECJia plugins 28.png

5、插件表单设置和获取

设置插件表单

点击测试插件,可以看到配置表单。

尝试输入Hello ECjia!,点击更新按钮,即可保存该值。

ECJia plugins 29.png

获取插件表单

在上面的实例中添加了 test_value 这个配置项,并设置为 Hello ECJIa! 那么如何获取呢:

使用getConfig方法即可获取,以下为范例:

// 获取配置文件的 test_value 的值,存到$test_value变量。
$test_value = $this->getConfig('test_value');
// 此时 $test_value 的值为 Hello ECJIa

6、使用公众平台测试工具调试插件返回内容

ECJia到家公众平台测试工具地址

https://testapi.ecjia.com/sites/wetest/

站点截图预览:

Daojia plugins 10.png.png

其中左边为配置区域:

配置名称 配置介绍
加密调试 调试模式。有明文模式,兼容模式,安全模式
appID 微信公众平台的appID
appsecret 微信公众平台的appsecret
URL 开发者填写URL,调试时将把消息推送到该URL上
Token 微信公众平台设置的Token
消息类型 各种消息事件,包含关注取消关注
发送用户 发送方帐号(一个OpenID)
接受用户 开发者微信号
内容 消息类型(文本消息内容)
发送消息 发送信息的内容,包含XML代码
接收消息 接受返回的内容,包含XML代码

右边为仿真的微信对话效果。

测试返回内容

举例子:测试 test插件 关键字回复的内容。

将左侧的加密调试设置为明文模式,消息类型设置为文本,内容为test

点击 检查问题 按钮,如果一切正常,会返回一个图文消息。

Daojia plugins 11.png

第三篇:插件高级配置

1、如何让插件仅支持平台或者商家

编辑插件配置文件 config.php ,修改 support_type 字段:

<?php
defined('IN_ECJIA') or exit('No permission resources.');

return array(
    // ......
    // 上省略
    
    // 只支持平台
    'support_type' => Ecjia\App\Platform\Plugin\PlatformAbstract::TypeAdmin,
    
    // 下省略
    // ......
}

support_type 可配置项:

  • 只支持平台:Ecjia\App\Platform\Plugin\PlatformAbstract::TypeAdmin,
  • 只支持商家:Ecjia\App\Platform\Plugin\PlatformAbstract::TypeMerchant,
  • 支持平台和商家:Ecjia\App\Platform\Plugin\PlatformAbstract::TypeAdmin | Ecjia\App\Platform\Plugin\PlatformAbstract::TypeMerchant,

2、如何让插件支持公众平台类型

编辑插件配置文件 config.php ,修改 sub_code 字段:

<?php
defined('IN_ECJIA') or exit('No permission resources.');

return array(
    // ......
    // 上省略
    
    // 仅支持微信服务号
    'support_platform_type' => ['service'], 
    
    // 下省略
    // ......
}

support_platform_type 可配置项:

  • service:服务号
  • unauthorized:未认证的服务号
  • subscribe:订阅号
  • test:测试号

配置项可多选,若要支持所有公众平台类型:

// 支持微信所有类型公众号
'support_platform_type' => ['service', 'unauthorized', 'subscribe', 'test'],

3、插件内如何判断商家或平台

获取类型是商家和平台可以通过 getStoreType 方法来获取:

// 获取类型
$type = $this->getStoreType();

// 如果为平台
if ($type = self::TypeAdmin) {
    // 处理平台绑定用户
    $content = $this->handleAdminBindUser();
} 
// 如果为商家
else if ($type = self::TypeMerchant) {
    // 处理商家绑定用户
    $content = $this->handleMerchantBindUser();
}

返回值

  • self::TypeAdmin:平台
  • self::TypeMerchant:商家

4、插件内如何转发请求到另一个插件

转发命令十分简单,已经封装成一句话:

// 转发到 mp_userbind 插件
return $this->forwardCommand('mp_userbind');

5、如何判断是否绑定用户

// ......
// 上省略

// 如果未绑定
if (! $this->hasBindUser()) {
	// 转发到 mp_userbind 插件
    return $this->forwardCommand('mp_userbind');
// 如果已绑定
} else {
	// 代码块省略
    // ......
}

// 下省略
// ......

6、子命令介绍与配置

子命令介绍

有时候某些功能大体都是一致的,区别很小,建议使用子命令,子命令可以让一个插件支持多个功能。

mp_goods这个微信公众平台插件是个典型的例子,他支持五个子命令,一个插件拥有5种功能。

  • best:精品商品
  • hot:热门商品
  • new:最新商品
  • recommend:推荐商品
  • promotion:促销商品

子命令配置

编辑管理配置文件mp_test.class.php,修改eventReply方法

    /**
     * 事件回复
     * {@inheritDoc}
     * @see \Ecjia\App\Platform\Plugin\PlatformAbstract::eventReply()
     */
    public function eventReply() {
        // 获取命令实例
        $commandInstance = $this->getCommandInstance();
        // 返回
        return $commandInstance->handleEventReply();
    }

新建getCommandInstance方法,通过getSubCodeCommand方法来获取子命令。

protected function getCommandInstance()
{
    // $this->getSubCodeCommand()获取子命令
    if ($this->getSubCodeCommand()) {
        switch ($this->getSubCodeCommand()) {
            // 子命令subfoo
            case 'subfoo':
                // 加载子命令管理配置文件
                require_once RC_Plugin::plugin_dir_path(__FILE__) . 'mp_test_subfoo.class.php';
                // 设置子命令对象参数
                $subCommand = $this->subCommand(new mp_test_subfoo());
                break;

                // 其他子命令
                
                // 默认命令
            default:
                $subCommand = $this->subCommand($this);
                break;
        }

        // 返回子命令数据
        return $subCommand;
    } else {
        return $this;
    }
}

新建mp_test_subfoo.class.php文件,下面为示例:

注意事项:子命令类继承主插件类,这里为mp_test

<?php

// 导入命名空间
use Ecjia\App\Wechat\WechatRecord;

defined('IN_ECJIA') or exit('No permission resources.');


// 注意继承主管理配置文件类 mp_test
class mp_test_subfoo extends mp_test
{   
    
    
    /**
     * 子命令事件回复
     */
    protected function handleEventReply() 
    {	
        // 简单的回复示例
        $articles = [
            'content'	=> '测试子命令'
        ];
        	
        return WechatRecord::News_reply($this->getMessage(), $articles['content']);
    }
}

// end

第四篇:插件页面控制器

1、介绍插件页面控制器

控制器是处理该插件有关逻辑的php文件,一般我们都创建一个默认为init的控制器为该应用的主控制器;当然你可以根据需要的情况以init_为前缀创建多个控制器。

2、控制器的命名规则介绍

RC_Uri::url('platform/plugin/show',array('handle' => 'mp_test/init',) 'openid' => openid, 'uuid' => uuid)

一般情况下,前面部分不需要改变,

代表平台插件地址,后面的参数将影响访问的插件地址:

  • 【handle】:插件名称【mp_test】/ 文件名
  • 【openid】:传递openid
  • 【uuid】:传递uuid

3、控制器的创建及示例

test 插件下新建 init.php

在插件跟目录新建一个 init.php 文件,加入以下继承类:

use Ecjia\App\Platform\Frameworks\Contracts\PluginPageInterface;
use Ecjia\App\Platform\Frameworks\Controller\PluginPageController;

然后新建一个 mp_zjd_init 类,注意继承:

类名命名规则:插件名 + 文件名

class mp_php_init extends PluginPageController implements PluginPageInterface

新建两个function:

public function init()
{
    //设置插件目录
    $this->setPluginPath(__FILE__);
    
    //加载插件js资源
    $this->assginPluginStyleUrl('test_js', 'js/test.js');
    $this->assginPluginStyleUrl('jquery_js', 'js/jquery.js');
    
    //代码省略,一般设置插件目录和设置资源URL
}
public function action()
{
    //初始化资源URL加载
    $this->init();
    
    // 下省略
    // ......
}

4、控制器内加载资源和调用模板

加载资源

  1. 在test插件根目录下创建css文件夹存储css文件
  2. 在test插件根目录下创建js文件夹存储js文件
  3. 在test插件根目录下创建images文件夹存储图片文件

Daojia plugins 12.png

编辑页面控制器 init.php 文件,加载资源:

注意事项:assginPluginStyleUrl方法,第一个参数为smarty变量名,第二个参数为文件相对路径。

public function init()
{
    //设置插件目录
    $this->setPluginPath(__FILE__);

    // 加载插件js资源
    // 第一个参数为smarty变量名,第二个参数为文件相对路径
    $this->assginPluginStyleUrl('test_js', 'js/test.js');
    $this->assginPluginStyleUrl('jquery_js', 'js/jquery.js');

    // 设置插件css资源
    // 第一个参数为smarty变量名,第二个参数为文件相对路径
    $this->assginPluginStyleUrl('test_css', 'css/test.css');
    $this->assginPluginStyleUrl('bootstrap_css', 'css/bootstrap.css');

    // 设置图片资源
    // 第一个参数为smarty变量名,第二个参数为文件相对路径
    $this->assginPluginStyleUrl('test_png', 'images/test.png');
}

public function action()
{
    //初始化资源URL加载
    $this->init();
    
    // 下省略
    // ......
}

调用模板

插件根目录下新建一个 templates 文件夹,然后在 templates 文件夹下新建一个 test_index.dwt.php 文件

test_index.dwt.php 为网站模板页,如果你需要多个访问页面可以新建多个:

ECJia plugins 15.png

然后只需要编辑页面控制器 init.php 文件,加入一行代码即可引用此页面:

// 引用templates目录下test_index.dwt.php模板页
ecjia_front::$controller->display($this->getPluginFilePath('templates/test_index.dwt.php'));

5、页面禁止微信客户端外打开

编辑页面控制器 init.php 文件,在 init 方法加入以下代码:

public function init()
{
    // ......
    // 上省略
    
    // 禁止微信客户端外打开
    if (!ecjia_is_weixin()) {
        $uuid = trim($_GET['uuid']);
        $url = with(new Ecjia\App\Wechat\Authorize\WechatAuthorize($uuid))->getAuthorizeUrl(RC_Uri::current_url());
        $this->redirect($url);
    }
    
    // 下省略
    // ......

}

第五篇:高级技巧

1、插件抽象方法介绍

  1. 获取iconurl:

    abstract public function getPluginIconUrl()
    
  2. 插件返回数据统一接口:

    abstract public function eventReply();
    
  3. 加载语言包:

    public function loadLanguage($key = null, $default = null);
    
    • $key:key值

    • $default:默认值

  4. 加载配置文件:

    public function loadConfig($key = null, $default = null);
    
    • $key:key值

    • $default:默认值

  5. 获取插件代号:

    public function getCode()
    

2、插件类常用方法介绍

  1. 获取子命令数组

    public function getSubCode()
    
  2. 获取默认插件使用命令

    public function getDefaultCommands()
    
  3. 设置消息

    public function setMessage($message)
    
    • $message:消息

  4. 获取消息

    public function getMessage()
    
  5. 获取 store_id

    public function getStoreId()
    
  6. 获取 openid

    public function getOpenId()
    
  7. 设置商家类型(平台,商家)

    public function setStoreType($store_type)
    
    • $store_type:商家类型。可选参数:TypeAdmin,TypeMerchant

  8. 获取商家类型(平台,商家)

    public function getStoreType()
    
  9. 设置公众号类型

    public function setPlatformTypeCode($platform_type)
    
    • $platform_type:公众号类型

  10. 获取公众号类型

    public function getPlatformTypeCode()
    
  11. 设置关键字

    public function setKeyword($keyword)
    
    • $keyword:关键字

  12. 获取关键字

    public function getKeyword()
    
  13. 获取该命令是否支持公众号

    public function hasSupport($store_type)
    
    • $store_type:商家类型

  14. 获取公众平台插件支持平台公众号

    public function hasSupportTypeAdmin()
    
  15. 转发命令,这里直接使用插件代号

    public function forwardCommand($ext_code, $sub_code = null)
    
    • $ext_code:插件代号

    • $sub_code:插件子命令

3、插件类动态方法介绍

  1. 检测公众平台粉丝是否绑定用户

    public function hasBindUser()
    
  2. 获取ECJIA user的user_id快捷方法

    public function getEcjiaUserId()
    
  3. 获取WechatUser对象

    public function getWechatUser()