二次开发文档:高级开发

后台显示字段回调

回调是用于在列表显示时对其值进行格式化,如果不填写回调函数,那么就会原样显示数据库储存内容。

CMS默认的回调函数有:

文本显示:dr_clearhtml
标题: title
评论专用: comment
多文件: files
uid会员: uid
栏目: catid
副栏目:catids
日期时间: datetime
日期: date
会员信息: author
地区联动: linkage_address
联动菜单(单选)名称: linkage_name
联动菜单(多选)名称: linkages_name
单选字段名称: radio_name
下拉字段名称: select_name
复选框字段名称: checkbox_name
实时存储文本值:save_text_value
实时存储选择值:save_select_value
单文件:file(4.5.3版本支持)
图片专用:image(4.5.3版本支持)
去掉html代码:text(4.6版本支持)
将html字符编码输出:code(4.6版本支持)
原样输出:get_value


傻瓜式调用系统自带的回调

1、标题: title

image

普通的文本显示,会加上a超链接

2、评论: comment

3、多文件: files(4.5.3以上版本支持)

{xunruicms_img_title}

4、uid会员: uid

image

根据uid参数显示账号信息,后台会点击查看详情

5、栏目: catid

image

通过栏目id来显示对应的栏目名称

副栏目:catids,原理同上,会显示多个栏目

6、时间: datetime

image

显示时间戳转为具体时间格式

7、会员信息: author

同(3),根据author账号字段参数显示账号信息,后台会点击查看详情

8、地区联动: linkage_address

image

适用于地区的联动字段名称显示

9、联动菜单名称: linkage_name

同(8)适用于任意联动菜单

10、单选字段名称: radio_name

显示单选字段的name值

11、下拉字段名称: select_name

显示下拉字段的name值

12、复选框字段名称: checkbox_name

显示复选字段的name值,支持多个显示

13、实时存储文本值:save_text_value

image

直接编辑字段,实现实时存储

14、实时存储选择值:save_select_value

模块内容自定义的字段这个怎么能改成这样的按钮

直接选择字段,实现实时存储状态值,这个字段对选项值有要求,只能是:1表示是,0表示否

image

比如这种,1表示上架,0表示下架

15、图片专用:image(4.5.3以上版本支持)

{xunruicms_img_title}

16、单文件:file(4.5.3以上版本支持)

二次开发自定义回调函数

如果需要其他回调方法怎么办?我们也提供开发者自己定义回调函数的方案


自定义函数文件:config/custom.php  

(如果是插件开发也可以放到插件的自定义函数文件中:/dayrui/App/应用目录/Config/Hooks.php


    // mytest是回调函数的名字
    // $value是传入的数据库值
    // $param是列表搜索的参数,可以忽略
    // $data是列表显示的全部值,可以忽略
    // $field是当前数据的字段属性数组,可以忽略
    function mytest($value, $param = [], $data = [], $field = []) {
        // 下面给传入的值加粗操作
        $html = "".$value."";
        return $html;
        
    }

重写系统Library类方法

当需要更改系统自带的Library类方法时,例如/dayrui/Fcms/Library/Router.php


1、新建文件:dayrui/My/Library/Router.php

2、新写方法体:

这里继承了系统Library类,可以重写系统类


重写系统Model类方法

当需要更改系统自带的Model类方法时,例如/dayrui/Fcms/Model/Member.php


1、新建文件:dayrui/My/Model/Member.php

2、新写方法体:

这里继承了系统Model模型类,可以重写系统类



全局自动加载Composer类

本教程仅限于CI内核使用(TP和LA内核自带Composer目录,分别是:dayrui/ThinkPHP/System/vendor和dayrui/Laravel/System/vendor)

Composer支持会自动初始化

它会自动读取文件: /vendor/autoload.php 

还可以自定义Composer目录,打开index.php写上:

define('COMPOSER_PATH', '填写绝对的autoload.php路径地址');
以QueryList类为例,如何自动加载进来呢?

1、通过QueryList官网的Composer命令下载源码到任意目录

2、将下载下来的vendor目录(这里是小写字母)复制到宸逸框架的目录:vendor/

image

确保目录结构一定要和图中的保持一致。

如果路径不对,后面会报错Class "QL\QueryList" not found。


3、新建test控制器来使用QueryList类,

dayrui/App/Test/Controllers/Test.php

控制器内容如下:

find('img')->attrs('src');
        //打印结果
        print_r($data->all());

        //采集某页面所有的超链接和超链接文本内容
        //可以先手动获取要采集的页面源码
        $html = file_get_contents('https://www.xunruicms.com');
        //然后可以把页面源码或者HTML片段传给QueryList
        $data = QueryList::html($html)->rules([  //设置采集规则
            // 采集所有a标签的href属性
            'link' => ['a','href'],
            // 采集所有a标签的文本内容
            'text' => ['a','text']
        ])->query()->getData();
        //打印结果
        print_r($data->all());
    }


}

这个例子代码是QueryList官方示例代码

4、运行程序地址:

http://www.xxxx.com/index.php?s=test&c=test&m=index

继承重写系统字段类别

当网站已经规划上线之后,数据集已经录入完成了,不方便删除重建字段的情况下,当需要改变一下系统字段的字段处理逻辑,在不破坏系统文件的前提下,可以继承系统的字段类别。

比如我要把系统默认的Text字段类型,改进一下,改成我自己的需求,本教程可以不影响升级的前提下进行开发



1、把系统的dayrui/Fcms/Field/Text.php内容复制到/dayrui/My/Field/Text.php

先一模一样的复制过去。


2、注意复制过来后,头部类方法 要成以下格式

其他逻辑代码你可以自由发挥的修改


这种方法属于继承重写的方法,改变系统自带的字段处理逻辑,二次开发时候可以用到


输出最后一次运行的SQL

\Phpcmf\Service::M()->get_sql_query();

输出最后一次执行的SQL语句

定义任务类型Cron

定义任务类型Cron

定义任务类型在二次开发使用会用到,将自己的任务加入到任务队列中执行

比如我要创建一个crm测试的程序,用于登录成功后处理某某程序代码

$rt = \Phpcmf\Service::M('cron')->add_cron(SITE_ID, "程序文件名", [
    'code1' => '参数1',
    'code2' => '参数2',
    'code3' => '参数3',
]);
if (!$rt['code']) {
    // 执行提交失败时返回false
}

1、在钩子文件中加入登录成功后的钩子写法

config/hooks.php

\Phpcmf\Hooks::on('member_login_after', function($data) {

    \Phpcmf\Service::M('cron')->add_cron(SITE_ID, 'crm', $data); // 命名为crm
    
});

支持插件目录形式的写法,例如:

\Phpcmf\Hooks::on('member_login_after', function($data) {

    \Phpcmf\Service::M('cron')->add_cron(SITE_ID, 'myapp::crm', $data); // 命名为crm
    
});

2、创建自定义任务类型文件

dayrui/My/Cron/Crm.php


支持插件目录形式的写法,例如:

dayrui/App/Myapp/Cron/Crm.php


3、内容格式如下:


// 返回格式
return '失败提示文字,成功不填写';


4、当登录成功后就会触发1中的脚本,进入后台的任务队列里面


在开发中,执行这个方法,时,就会加入到任务队里中了


可以通过设置服务器进行自动执行任务

自定义模板解析list标签

需要精通php的开发者使用


系统自带的标签有

{category **** } 获取栏目 {/category}
{linkage  ****}  获取联动菜单 {/linkage}
{related ****}        相关文章 {/related}
{sql ****}            sql查询 {/sql}
{table ****}          数据表查询 {/table}
{form ****}           站点表单循环 {/form}
{mform ****}          模块表单循环 {/mform}
{member ****}         会员循环 {/member}
{module ****}         循环模块数据 {/module}
{search ****}         模块搜索 {/search}
******等等


如果自带的模板标签满足不了你的需求,开发者可以进行自定义模板标签,比如自定义:

{list action=mytag app=myapp ****}    自己的输出代码 {/list}


实现步骤:

1、创建标签业务文件,Action文件夹默认不存在,需要手动创建

dayrui/App/Myapp/Action/Mytag.php

mytag就是标签的名称,不要带符号和数字,首字母大写,最好是英文组合,长度不限

myapp是应用插件的目录


2、Mytag.php文件格式要求:

 123],
];

return $this->_return($system['return'], $data, $sql, $total, $pages, $pagesize);


3、标签调用

{list action=mytag app=myapp v1=参数1 v2=参数2 ****** }
{$t.name}
{$t.test}
{/list}
{$debug}


Table类:查询条件继承

适用于继承table类的控制器文件,需要精通php的开发者


功能介绍:在列表数据增加一组查询条件,比如在后台的新闻列表页面增加一个固定条件判断


用法说明:

在继承_List()函数之前写上

$where = "你的sql条件";
if ($this->init['where_list']) {
    $this->init['where_list'].= " AND ".$where;
} else {
    $this->init['where_list'] = $where;
}


以demo模块的内容列表控制器为例:https://www.xunruicms.com/doc/876.html



发送手机验证码开发

用在二次开发时,处理验证码发送程序,适合精通php的程序员


模板代码:


	图片验证
	
		
			
			
				{dr_code(120, 35)}
			
短信验证 获取手机验证码

id传递手机号码


程序判断部分:

$code = \Phpcmf\Service::L('Form')->get_mobile_code($phone);
if (!$code) {
	$this->_json(0, dr_lang('没有发送验证码'));
} elseif ($code != $_POST['sms']) {
	$this->_json(0, dr_lang('验证码不正确'));
}


格式化字段输入表单

可以在发布表单中自定义自己的字段样式,默认的,系统使用 {$myfield}等等的变量输出的系统字段布局样式:


    字段中文名字
    字段控件html代码


情况一:

如果想把系统字段布局样式改成这种呢?


    字段中文名字
    字段控件html代码


需要配置系统文件,新建或修改以下文件

/config/field.php


配置格式为:

 '
    {text}
    {value}
',
    
    'member' => '
    {text}
    {value}
',
    
];


其中 home 表示前端界面的样式、member表示用户中心的界面样式、admin表示后台界面的样式


标签说明:

{name} 字段英文名
{text} 字段中文名字
{value} 字段控件html代码

三个标签缺一不可


情况二:

 {$myfield}

这个标签会加载当前表单的全部字段,那么问题来了,我想单独输出这些字段怎么办?

比如有字段:title、thumb、file、cotent,我要单独调用这些字段表单,放到不同的页面位置


模块字段 title 的写法:

{dr_fieldform($ci->module['field']['title'], $title)}

模块字段 thumb 的写法:

{dr_fieldform($ci->module['field']['thumb'], $thumb)}


自定义跨站提交验证字段

站内提交表单都会触发跨站验证程序,如果提交表单中不包含csrf_token字段就会触发禁止提交

如何自定义csrf_token字段?


方法一、form提交的html代码


{dr_form_hidden()} 这句就是生产csrf_token的

或者


方法二、Ajax提交,必须在html界面使用

{csrf_token()} : "{csrf_hash()}"
var postData = {
 data: {
  title: askFormUserName,
  dianhua: askFormUserPhone,
  youxiang: askFormUserEmail,
  xuqiujianshu: askFormUserDescription,
 },
 {csrf_token()}: "{csrf_hash()}",
code: askFormUserCode
};


关键词获取接口开发

本接口用于接入第三方关键词获取接口来替换系统自带的百度关键词接口,比如阿里云分词接口、腾讯云分词接口


1、自定义函数文件

/config/costom.php


2、新增函数

/**
 * 提取关键字
 */
function dr_get_keywords($content, $siteid = SITE_ID)
{

    if (!$content) {
        return '';
    }

    // 这里写你的接口代码
    
    return '关键词,关键词2,关键词3';
}

$content 是需要提取关键词的文字内容

$siteid 是站点id,基本上用不着



网站表单/全局表单的导入

开发者创建表单后,需要导入到现有或其他系统中,可以使用本方法执行导入脚本:

\Phpcmf\Service::M('Form')->import("生成的表单字符串");


生成的表单字符串:

image.png

Table类:发布初始化值

适用于继承table类的控制器文件,需要精通php的开发者

功能介绍:发布内容时进行字段值初始化默认值,比如发布内容时,给title字段初始化一个值


用法说明:

1、打开内容模块发布控制器

/dayrui/App/Demo/Controllers/Admin/Home.php

在类中增加:

  /**
     * 获取内容
     * $id      内容id,新增为0
     * */
    protected function _Data($id = 0) {

        $data = parent::_Data($id);
        if (!$id) {
            // 表示新增数据
            $data['title'] =  "这是新增时的默认值";
        }

        return $data;
    }


2、发布内容时就会看到默认值:

image.png

连接多个数据库/数据源

xunruicms可以连接多个数据库操作


改配置文件config/database.php

 '127.0.0.1',
    'username' => 'xunruicms',
    'password' => 'xunruicms',
    'database' => 'xunruicms',
    'DBPrefix' => 'dr_',
];

// test是我们连接的第二个数据库
$db['test']     = array(
    'hostname' => '127.0.0.1',
    'username' => 'xunruicms2',
    'password' => 'xunruicms2',
    'database' => 'xunruicms2',
    'DBPrefix' => 'dr_',
);


程序中调用test数据库的写法(4.6版本及其以上)

// 连接数据库
list($db) = \Frame\Model::_load_db_source("test");
// 查询数据库
$db->query('YOUR QUERY HERE');



模板中的写法

必须使用sql标签:https://www.xunruicms.com/doc/425.html

比如查询test库的member表

{php $query=urlencode('select * from dr_member');}
{sql sql='$query' db=test}
{$t.username}
{/sql}
{$debug}

db=test,表示此sql查询指定的外部数据库

百度地图定位浏览器坐标

需要安装官方版的<百度地图字段插件


1、百度地图定位浏览器坐标并保存到cookie

{dr_baidu_position_js("自定义字段名称")}

那么在php中读取定位信息代码:

\Phpcmf\Service::L('input')->get_cookie('map_position');

有效性3个小时


2、百度地图定位浏览器坐标并设置为隐藏表单域

{dr_baidu_map_form_hidden("自定义字段名称")}

最终解析为:


那么在php中读取定位信息代码:

\Phpcmf\Service::L('input')->get_cookie('map_position');

有效性3个小时


3、百度地图定位浏览器坐标实时获取

{dr_baidu_map_js()}

    // 百度地图定位坐标
    var geolocation = new BMap.Geolocation();
    geolocation.getCurrentPosition(function(r){
        if(this.getStatus() == BMAP_STATUS_SUCCESS){
            var pos = r.point.lng+','+r.point.lat;
            alert('定位成功:'+pos);
        } else {
            alert('定位失败:'+this.getStatus());
        }
    },{enableHighAccuracy: true});


Table类:增加列表查询条件

适用于继承table类的控制器文件,需要精通php的开发者

功能介绍:在分页列表中自建一些条件查询,比如模块内容管理列表时,给他加一个条件,比如aaa=1的内容


用法说明:

1、打开内容模块列表控制器

/dayrui/App/Demo/Controllers/Admin/Home.php


2、变更list继承的方法类 index

public function index() {

       $where = 'aaa=1'; // 新的条件组合
       if ($this->init['where_list']) {
           $this->init['where_list'].= ' AND '.$where;
           // 考虑到父类也许有可能会自带条件,防止被覆盖默认条件,所以追加一个 AND
       } else {
           $this->init['where_list'] = $where;
       }

       $this->_Admin_List();
}


这样列表数据就多加一个自定义条件了

image

Table类:重写列表查询的数据格式

适用于继承table类的控制器文件,需要精通php的开发者

功能介绍:在分页列表中返回的数据,进行二次组装,比如模块内容管理列表时,要给返回结果多增加一些数据


用法说明:

1、打开内容模块列表控制器

/dayrui/App/Demo/Controllers/Admin/Home.php


2、变更list继承的方法类 index

public function index() {

       \Phpcmf\Service::V()->set_return(true);
       $rt = $this->_Admin_List();
       if ($rt) {
           // 抓出数据
           $list = \Phpcmf\Service::V()->get_value('list');
           if ($list) {
               foreach ($list as $i => $t) {
                   $list[$i]['new'] = '这是新赋值的变量';
               }
           }
           // 重新赋值给模板
           \Phpcmf\Service::V()->set_value('list', $list);
           \Phpcmf\Service::V()->set_return(false);
           \Phpcmf\Service::V()->display($rt);
       }
}


那么在列表中就能调查new这个新赋值的变量了

自定义支付方式接口

系统内置了微信、支付宝等支付方式,比如你需要自己接入第三方支付接入,例如京东、网银等,需要参考此教程

本教程需要精通php开发的技术人员


一、支付方式目录结构

image

目录命名必须是英文字母


二、必备文件介绍

image

1、config.php 是支付信息文件,说明这个支付方式是什么名字

 '新的支付',
    'icon' => '',
    
];


2、notify_js.php 是单击未付款按钮时的提示信息

 1, 'msg' => ''];

image

3、pay.php 用于发起支付程序

4、setting.php 后台配置支付数据


    配置信息11
    
        ][value11]" rows="5">

    
    配置信息22              ][value22]" rows="5">     

image


5、notify_url.php 回调地址的入口文件,内容是固定格式


6、notify_api.php 回调地址的执行文件


远程附件下载入库

开发时需要将远程的文件下载到本站服务器数据库进行数据存储管理


附件下载代码:

// 下载远程文件
$rt = \Phpcmf\Service::L('upload')->down_file([
    'url' => "https://xxxxxx.com/xxxx.jpg",//url必须以扩展名结尾
    'attachment' => \Phpcmf\Service::M('attachment')->get_attach_info(0), // 0值不属于存储策略,填写策略ID号表示附件存储策略,可以是远程存储,可以是本地存储,如果不用存储策略就填0
]);
if ($rt['code']) {
    // 上传成功
    // $rt['data'] 附件入库后的信息数据


    // 附件归档 可选
    $att = \Phpcmf\Service::M('attachment')->save_data($rt['data'], '归档字符串,自定');
    if ($att['code']) {
        // 归档成功
       
    }

} else {
    // 下载失败 返回的错误
    $rt['msg']; 
}


后台顶部菜单定义

image

后台每个页面的顶部导航菜单的定义方法


在控制器中定义菜单变量格式:

\Phpcmf\Service::V()->assign([
    'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
        [
            // 通用菜单
            '菜单名称' => ['APP目录名称/控制器名称/方法名称', 'fa fa-wrench'],
            
            // 弹出窗菜单
            '弹出菜单名称' => ['add:APP目录名称/控制器名称/方法名称', 'fa fa-plus-square', '70%'], 
            
            // 隐藏菜单是通常在修改或查看页面会用到
            '隐藏菜单名称' => ['hide:APP目录名称/控制器名称/方法名称', 'fa fa-edit'],
            
            // 帮助菜单
            'help' => [123], // 123是官方帮助手册中的id号
        ]
    ),
]);


1、通用菜单举例

image

控制器名称:/dayrui/App/Demo/Controllers/Admin/Menu.php

\Phpcmf\Service::V()->assign([
    'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
        [
            // 通用菜单
            '菜单名称' => ['demo/menu/index', 'fa fa-wrench'],
        ]
    ),
]);

demo/menu/index 是控制器的uri地址

fa fa-wrench 是当前菜单的图标符号


2、弹出式菜单

image

控制器名称:/dayrui/App/Demo/Controllers/Admin/Menu.php

\Phpcmf\Service::V()->assign([
    'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
        [
            // 通用菜单
            '菜单名称' => ['demo/menu/index', 'fa fa-wrench'],
            // 弹出窗菜单
            '弹出菜单名称' => ['add:demo/menu/add', 'fa fa-plus-square', '30%'],
        ]
    ),
]);

demo/menu/add 是弹出式菜单的控制器的uri地址

fa fa-plus 是当前菜单的图标符号

30% 是弹出式菜单的宽度


3、隐藏式菜单

image

只有进入这个控制器才会显示菜单,如果不进入当前控制器就不会显示

控制器名称:/dayrui/App/Demo/Controllers/Admin/Menu.php

\Phpcmf\Service::V()->assign([
    'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
        [
            // 通用菜单
            '菜单名称' => ['demo/menu/index', 'fa fa-wrench'],
            // 弹出窗菜单
            '弹出菜单名称' => ['add:demo/menu/add', 'fa fa-plus-square', '30%'],
            '隐藏菜单名称' => ['hide:demo/menu/edit', 'fa fa-edit'],
        ]
    ),
]);

demo/menu/edit 是隐藏式菜单的控制器的uri地址

fa fa-edit 是当前菜单的图标符号


4、在线帮助菜单

image

单击在线帮助即可访问官网帮助手册中的对应手册文章内容

控制器名称:/dayrui/App/Demo/Controllers/Admin/Menu.php

\Phpcmf\Service::V()->assign([
    'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
        [
            // 通用菜单
            '菜单名称' => ['demo/menu/index', 'fa fa-wrench'],
            // 弹出窗菜单
            '弹出菜单名称' => ['add:demo/menu/add', 'fa fa-plus-square', '30%'],
            // 在线帮助
            'help' => [15],
        ]
    ),
]);

15 是宸逸官网手册文档的id号


网站表单/全局表单提交后的回调开发

网站表单提交后的动作可以使用钩子完成:https://www.xunruicms.com/doc/292.html

还可以通过修改表单控制器的的回调函数来完成

打开表单控制器文件:dayrui/App/Form/Controllers/Test.php

_Home_List();
    }

    public function show() {
        $this->_Home_Show();
    }

    public function post() {
        // 提交前的操作
        
        // 提交处理
        $this->_Home_Post();
    }
    
    // 新增回调函数
     protected function _Call_Post($data) {
        $cp = parent::_Call_Post($data);
        if ($cp['code']) {
            // 这里写 提交成功时的 你的程序代码
            $this->_json($cp['code'], '提交表单成功', $cp['data']);
        } else {
            $this->_json(0, '提交失败', $cp['data']);
        }
    }
}


栏目过多时的解决方案

我们做过很多大型的网站,规划好栏目后都不会超过50个,对于网站来说,栏目设置的越多就越麻烦,不仅后期运营起来会加重工作量,也会影响网站优化。

栏目设置的越多,添加的资料也就越多,网站的负担就会越重,无形之中会导致网站加载速度变慢,影响用户体验。

网站栏目就好比一本书的目录,对网站的整体内容进行分类,是为了帮助搜索引擎蜘蛛和用户更好的浏览网站。如果栏目过多,过于繁杂,就会给搜索引擎蜘蛛爬行造成阻碍,影响爬行效率,是非常不利于网站优化的。

对于后期坚持进行更新和运营,网站栏目如果设置过多,每个栏目都需要添加资料,对于没有专业运营人员的企业来说,无疑就加大了工作量,提高了运营成本。

-----------------------

综上所述,网站建设并不是设置的栏目越多越好。

那么,如果遇到项目中需要多层级的分类目录关系怎么办呢?

按我们的开发经验,可以分为以下几种方案,可以大大提高网站运维效率。



解决方案一:使用《联动菜单》作为栏目的分类子类(这种方法也不是唯一的方案,具体需要按网站的实际需求来想方案)

1、后台,创建联动菜单,暂时命名为:二级栏目image


2、创建好之后,可以进行数据录入,联动菜单可承受上万的数据量

image


3、再返回到模块管理,进入模块自定义字段,创建一个子类字段,关联到此联动菜单

image


4、返回到内容管理,发布界面时即可看到这个字段选项了


解决方案二:使用独立模块作为类别

1、后台,创建模块

2、安装刚才创建的模块,选择独立模块

3、进入内容管理-栏目管理-选择创建的独立模块名称

4、进入独立模块的栏目管理列表,添加和维护栏目



--------------------------

优化栏目更新速度:

1、打开网站入口文件index.php

2、增加以下代码:

#栏目更新阈值,当超过200栏目时进行分批次更新栏目
define('MAX_CATEGORY', 200);


当设置数量超过100时,建议把php内存上限设置大一些

memory_limit 999999M

image

Table类:后台自定义条件筛选查询

基于Table类开发的后台控制器支持自定义条件查询,例如:

image

cms框架内置了常用的模糊匹配和时间段匹配方式

在开发中,会有增加筛选查询条件的需求,下面来介绍如何把某些自定义字段作为查询条件增加上去


1、首先需要在控制器中定义开启变量,例如控制器:dayrui/App/Demo/Controllers/Admin/Home.php

    // 数据表初始化
    protected function _init($data) {
        $this->is_diy_where_list = 1;
        return parent::_init($data);
    }


image

增加这个控制变量,表示此控制器开启自定义条件搜索


2、在对应的模板中添加搜索条件,默认搜索表单是这样的代码:

image

添加条件格式也要采用form的方式,也就是把代码加到form里,例如我要添加一个自定义字段aaa搜索,搜索这个aaa值,写法是:

当填写aaa值的时候,会组合进现有的搜索条件中,按AND来组装SQL

模块表单提交后的回调开发

模块表单提交后的动作可以使用钩子完成:https://www.xunruicms.com/doc/931.html

还可以通过修改表单控制器的的回调函数来完成

打开表单控制器文件:dayrui/App/Demo/Controllers/Test.php

_Home_List();
    }

    public function show() {
        $this->_Home_Show();
    }

    public function post() {
        // 提交前的操作
        
        // 提交处理
        $this->_Home_Post();
    }
    
    // 新增回调函数
     protected function _Call_Post($data) {
        $cp = parent::_Call_Post($data);
        if ($cp['code']) {
            // 这里写 提交成功时的 你的程序代码
            $this->_json($cp['code'], '提交表单成功', $cp['data']);
        } else {
            $this->_json(0, '提交失败', $cp['data']);
        }
    }
}



自定义存储类型

image

针对存储类型的自定义,比如需要接入其他厂商的云存储


存储类型程序定义目录:

dayrui/ThirdParty/Storage


准备工作:

预定义一个文件名,有字母组成,例如是Test


开发步骤:

1、存储类型命名配置

dayrui/ThirdParty/Storage/Test/App.php

内容如下:

 10, // 这里写10以上99以下的id号
    'name' => 'TEST', // 这里是存储类型的命名,例如图一的部分

];

3、参数文件格式

dayrui/ThirdParty/Storage/Test/Config.html

内容如下:


    服务器地址
    
        
         这里是服务器地址参数 
    
    其他信息                        这里是其他信息参数      

注意,以上的 class="form-group r10 r" 和 data[value][10],中 的10就是(1)中定义的id号,必须对应起来

那么,后台效果就是

image


3、新建业务运行程序文件

dayrui/ThirdParty/Storage/Test.php

内容如下:

filename = trim($filename, DIRECTORY_SEPARATOR);
        $this->filepath = dirname($filename);
        $this->filepath == '.' && $this->filepath = '';
        $attachment['value']['path'] = rtrim($attachment['value']['path'], DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
        $this->attachment = $attachment;
        $this->fullpath = $this->attachment['value']['path'].$this->filepath;
        $this->fullname = $this->attachment['value']['path'].$this->filename;

        return $this;
    }

    // 文件上传模式
    public function upload($type = 0, $data, $watermark) {

        $this->data = $data; // 
        $this->watermark = $watermark; // 是否水印变量

        // 本地临时文件
        $locpath = WRITEPATH.'attach/'.md5($this->fullname);
        
        // 存储文件 移动上传或者内容存储
        if ($type) {
            // 移动失败
            if (!(move_uploaded_file($this->data, $locpath) || !is_file($locpath))) {
                return dr_return_data(0, dr_lang('文件移动失败'));
            }
        } else {
            $filesize = file_put_contents($locpath, $this->data);
            if (!$filesize || !is_file($locpath)) {
                return dr_return_data(0, dr_lang('文件创建失败'));
            }
        }
       
        // 强制水印
        if ($this->watermark) {
            $config = \Phpcmf\Service::C()->get_cache('site', SITE_ID, 'watermark');
            $config['source_image'] = $locpath;
            $config['dynamic_output'] = false;
            \Phpcmf\Service::L('Image')->watermark($config);
        }
        $md5 = md5_file($locpath);
        
        // $this->filename 这个是文件存储的相对路径 
        
        /*
        这里写你的上传到文件服务器代码
        $locpath 本地文件
        $this->attachment 服务器配置信息
        
        如果遇到错误的返回格式:
        return dr_return_data(0, '错误信息');
        */
        
        
        // 上传成功的返回
        return dr_return_data(1, 'ok', [
            'url' => $this->attachment['url'].$this->filename,
            'md5' => $md5,
        ]);
    }

    // 删除文件 
    public function delete() {
        // 这里写删除文件的方法
    }


}




自定义入口程序

用于不带任何参数的url来访问控制器文件,例如

http://www.xxx.com/aaaa.php 访问控制器 某某某
http://www.xxx.com/api/bbb.php 访问控制器 某某某


示例说明

1、新建入口文件:/api/test.php(不限大小写)


2、新建控制器文件:./dayrui/My/Api/Test.php(文件首字母需要大写)


3、访问此文件:

http:/xxxx.com/api/test.php

输出结果是:

123


自定义搜索seo变量{param}字符串

当搜索seo设置参数中包含了 {param} 标签时,会自动根据浏览器参数来组装网页的title字符串,比如

image

在实际项目中需要变更内容时,比如把栏目名称去掉,那么可以重写content类完成操作


1、新建或打开文件

dayrui/App/Demo/Models/Content.php


2、修改seo方法


比如还可以将字符串文字进行转换,例如

image

上例子是获取的某些字段的范围值,比如我想改成:2000到3000


1、新建或打开文件

dayrui/App/Demo/Models/Content.php


2、修改seo方法


网站表单/全局表单入库插入方法

在php程序中对网站表单入库插入的操作,首先要明白网站表单的数据表结构


本教程需要精通php技术的开发人员使用


一、表结构

1、主表:dr_1_form_网站表单名称

固定字段介绍

id    自增
uid    作者id
author 作者账号名
title    标题主题
inputtime    入库时间
inputip    入库IP地址
status    审核值,1通过,0待审
displayorder 排序值
tableid 对应的附表id

2、附表:dr_1_form_网站表单名称_data_0,0是标号,数据达到一定量时自动增加附表分表

固定字段介绍

id    自增
uid    作者id


二、插入方法

$data = [];
$data['title'] = '标题测试';
$data['status'] = 1;
$data['uid'] = (int)$this->member['uid'];
$data['author'] = $this->member['username'];
$data['inputip'] = \Phpcmf\Service::L('input')->ip_address();
$data['inputtime'] = SYS_TIME;
$data['tableid'] = 0;
$data['displayorder'] = 0;
// 插入主表
$rt = \Phpcmf\Service::M()->table_site("form_表单名称")->insert($data);
if (!$rt['code']) {
    exit("插入失败:".$rt['code']);
}

// 如果要使用附表分表就 按一定量进行分表设置 比如50000
$data['tableid'] = floor($rt['code']/50000);
\Phpcmf\Service::M()->table_site("form_表单名称")->update($data['id'], ['tableid' => $data['tableid']]);

$data2 = [];
$data2['id'] = $rt['code'];
$data2['uid'] = (int)$this->member['uid'];
// 插入附表
$rt = \Phpcmf\Service::M()->table_site("form_表单名称_data_".$data['tableid'])->insert($data2);
if (!$rt['code']) {
    // 删除主表
    \Phpcmf\Service::M()->table_site("form_表单名称")->delete($data['id']);
    exit("插入失败:".$rt['code']);
}


模块表单入库插入方法

在php程序中对模块表单入库插入的操作,首先要明白模块表单的数据表结构


本教程需要精通php技术的开发人员使用


一、表结构

1、主表:dr_1_模块目录_form_表单名称

固定字段介绍

id    自增
uid    作者id
author 作者账号名
cid    模块内容id
catid    模块的栏目id
title    标题主题
inputtime    入库时间
inputip    入库IP地址
status    审核值,1通过,0待审
displayorder 排序值
tableid 对应的附表id

2、附表:dr_1_模块目录_form_表单名称_data_0,0是标号,数据达到一定量时自动增加附表分表

固定字段介绍

id    自增
uid    作者id
cid    模块内容id
catid    模块的栏目id


二、插入方法

$data = [];
$data['title'] = '标题测试';
$data['status'] = 1;
$data['catid'] = 1; // 栏目id
$data['cid'] = 1; // 内容id
$data['uid'] = (int)$this->member['uid'];
$data['author'] = $this->member['username'];
$data['inputip'] = \Phpcmf\Service::L('input')->ip_address();
$data['inputtime'] = SYS_TIME;
$data['tableid'] = 0;
$data['displayorder'] = 0;
// 插入主表
$rt = \Phpcmf\Service::M()->table_site("模块目录_form_表单名称")->insert($data);
if (!$rt['code']) {
    exit("插入失败:".$rt['code']);
}

//$data['tableid'] = 1;
//\Phpcmf\Service::M()->table_site("模块目录_form_表单名称")->update($data['id'], ['tableid' => $data['tableid']]);

$data2 = [];
$data2['id'] = $rt['code'];
$data2['uid'] = (int)$this->member['uid'];
$data2['catid'] = 1; // 栏目id
$data2['cid'] = 1; // 内容id
// 插入附表
$rt = \Phpcmf\Service::M()->table_site("模块目录_form_表单名称_data_".$data['tableid'])->insert($data2);
if (!$rt['code']) {
    // 删除主表
    \Phpcmf\Service::M()->table_site("模块目录_form_表单名称")->delete($data['id']);
    exit("插入失败:".$rt['code']);
}
// 更新表单数量到模块内容主表
$total = \Phpcmf\Service::M()->table_site('模块目录_form_表单名称')->where('status', 1)->where('cid', $data['cid'])->counts();
\Phpcmf\Service::M()->table_site('模块目录')->update($data['cid'], [
    '表单名称_total' => $total,
]);


调用站外数据库

在xunruicms中可以调用除开本站以外的数据库,配置文件config/database.php

 'localhost',
    'username' => 'root',
    'password' => 'root',
    'database' => 'cms',
    'DBPrefix' => 'dr_',
];

// 这个cms2是站外的数据库信息
$db['cms2']    = [
    'hostname' => '192.168.2.12',
    'username' => 'root',
    'password' => 'root',
    'database' => 'cms2',
    'DBPrefix' => 'dede_',
];


例1、在PHP程序中的调用方法是:

// 连接cms2数据库
$db2 = \Config\Database::connect('cms2', false);
// 通过db2查询 cms2的member表数据
$rt = $db2->table("member")->get()->getResultArray();
var_dump($rt);


例2、在模板标签中使用sql标签调用外部数据库的表

{php $query=urlencode('select * from dede_member');}
{sql db=cms2 sql='$query'}
{$t.id}
{/sql} {$pages} {$debug}


当前用户能访问的模块栏目集合

$catids = implode(', ', array_keys(\Phpcmf\Service::C()->_module_member_category(\Phpcmf\Service::L('cache')->get('module-1-news', 'category'), 'news', 'show')));

表示当前登录的会员,具备news模块的所有可访问的权限栏目,id集合,1,2,3,4,5,6

重组重定义后台菜单字符串

cms系统会根据用户在后台设置的菜单数据来生成新的菜单布局html代码,{$string},比如以下代码就是由系统生成的

image

比如开发者需要在某些菜单里面加一个class,加一个id,加一段js代码,那么这种需求就需要 进行重组这些生成的代码


实现方法


一、后台完整菜单

打开文件config/custom.php,定义函数

function dr_my_admin_menu($menu, $string, $mstring, $menu_top, $first) {

    // 这里写你的代码
    
    // $menu是后台菜单集合数组
    // $string pc端菜单字符串
    // $mstring 移动端菜单字符串
    // $menu_top 顶部菜单数组
    // $first 首个菜单项目
    
    return array($menu, $string, $mstring, $menu_top, $first)
}


二、后台简化菜单

打开文件config/custom.php,定义函数

function dr_my_admin_min_menu($menu, $string) {

    // 这里写你的代码
    
    // $menu是后台菜单集合数组
    // $string 菜单字符串
    
    return $string;
}



联动菜单字段的自定义程序文件

不功能已经不再提供使用

适用于表单提交界面的联动菜单选择提示语句

image

比如选了“成都”就即时显示“他的自定义属性值”,选了“自贡”就即时显示“自贡的自定义属性属性”


我们以demo模块为例子


1、新建内容模块字段:联动菜单字段(单选)

image

这里显示自定义程序:选择默认的test.php

你也可以把test.php重命名另外一个文件再选择新文件

2、在提交页面就可以看到如下信息

image

上图红色区域就是test.php输出的附加属性值


如果要改变这个文字提示,我们可以回到(1)中的test.php文件,打开这个文件:


我们要改变的话就直接改变这两个变量值:

$html.= '这是['.$data['name'].']的地盘';
$edit_html.= '这是['.$data['name'].']的地盘';

这里的$data是联动菜单字段数组,我们也可以输出联动数据的其他字段,例如code字段可以改写为:

$html.= '这是['.$data['code'].']的地盘';
$edit_html.= '这是['.$data['code'].']的地盘';


第三方登录类型开发

系统默认自带的第三方登录方式有:微信扫描登录、新浪微博、QQ登录、微信公众号关注登录。

在实际项目中比如有人要增加一个登录方式呢,例如增加百度登录、微信APP端登录等等,这时候可以按本章来自定义登录方式。


本教程需要有一定的PHP开发基础!!


程序目录介绍:

dayrui/ThirdParty/OAuth/登录方式命名(首字母大写其余小写)/


文件介绍:

1、命名文件

dayrui/ThirdParty/OAuth/登录方式命名/App.php

 '微博', // 接入商名称
    'help' => 588, // 帮助手册id
];


2、运行文件

dayrui/ThirdParty/OAuth/登录方式命名/Run.php

getAuthorizeURL($callback_url));
}


3、配置好了文件,我们可以在后台看到新的登录方式,并设置参数

image


CLI模式下运行你的程序

除了 通过浏览器中的URL 调用应用程序的控制器外,还可以通过命令行界面(CLI)加载它们。

从命令行运行宸逸CMS的原因很多,比如

使交互式“任务”可以执行诸如设置权限,修剪缓存文件夹,运行备份等操作。

与其他语言的其他应用程序集成。例如,随机的C ++脚本可以调用一个命令并在模型中运行代码!


让我们创建一个简单的控制器,以便您可以实际看到它。

比如:/dayrui/App/My/Controllers/Test.php

使用您的文本编辑器,并将以下代码放入其中:

get('name');
    }

}

这是一个非常简单的标准控制器,我们可以通过下面URL来访问他

image

通过命令行模式访问:

image

进入cms根目录,运行的格式为:

php.exe index.php s=my c=test m=index name=888


前端用户登录时对密码进行加密传输

使用场景:网页中登录窗口提交密码传输、APP或小程序的API密码传输

本例以网页登录窗口登录为例,默认情况下的登录代码是:


    
        
        
    
                                 登录 

其中password字段是明文的,在提交请求的post记录中可以看到明文的密码字符串,那么如何进行加密这个密码呢


加密原理:

只需要将password字符串进行32位md5加密就行了,加密后传输32位值


实现方法:

1、引入jquery.md5的js文件


2、执行代码:


    
        
        
    


    
        
        
        
    



     登录 


MySQL数据优化

数据优化是一个大学问,本节部分内容来自百度

一、模板标签

模板标签写法不合理时会导致cpu占用过高,网站缓慢,不推荐使用的标签

module=all 全模块查询严重影响速度
related 相关标签,按关键词查询影响速度 order=rand 避免这种随机排序,严重影响速度


二、创建索引

最简单也是最常用的优化就是查询。因为对于CRUD操作,read操作是占据了绝大部分的比例,所以read的性能基本上决定了应用的性能。对于查询性能最常用的就是创建索引。经过测试,2000万条记录,每条记录200字节两列varchar类型的。当不使用索引的时候查询一条记录需要一分钟,而当创建了索引的时候查询时间可以忽略。但是,当你在已有数据上添加索引的时候,则需要耗费非常大的时间。我插入2000万条记录之后,再创建索引大约话费了几十分钟的样子。

创建索引的弊端和场合。虽然创建索引可以很大程度上优化查询的速度,但是弊端也是很明显的。一个是在插入数据的时候,创建索引也需要消耗部分的时间,这就使得插入性能在一定程度上降低;另一个很明显的是数据文件变的更大。在列上创建索引的时候,每条索引的长度是和你创建列的时候制定的长度相同的。比如你创建varchar(100),当你在该列上创建索引,那么索引的长度则是102字节,因为长度超过64字节则会额外增加2字节记录索引的长度。


1、为搜索字段建索引

索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。


2、千万不要 ORDER BY RAND() 和order=rand标签

想打乱返回的数据行?随机挑一个数据?真不知道谁发明了这种用法,但很多新手很喜欢这样用。但你确不了解这样做有多么可怕的性能问题。

如果你真的想把返回的数据行打乱了,你有N种方法可以达到这个目的。这样使用只让你的数据库的性能呈指数级的下降。这里的问题是:MySQL会不得 不去执行RAND()函数(很耗CPU时间),而且这是为了每一行记录去记行,然后再对其排序。就算是你用了Limit 1也无济于事(因为要排序)


3、在Join表的时候使用相当类型的例,并将其索引

如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。

而且,这些被用来Join的字段,应该是相同的类型的。例如:如果你要把 DECIMAL 字段和一个 INT 字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。(两个表的字符集有可能不一样)


4、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。


5、应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。


6、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。


三、读写分离

用两台或者多台主机做集群,一般是一写多读(一台mysql只写入,剩下的用来读取,写入的数据要实时的从写库同步到读库)这个配置起来也比较简单,唯一要说的是代理插件的选择,推荐360开源的atlas,用法很简单,实际使用中也没有太多bug。


四、数据表分区

什么是分区?

分区和分表相似,都是按照规则分解表。不同在于分表将大表分解为若干个独立的实体表,而分区是将数据分段划分在多个位置存放,分区后,表还是一张表,但数据散列到多个位置。

另外分区也可以分为两种:

垂直分区和水平分区

水平分区(Horizontal Partitioning)这种形式分区是对表的行进行分区,所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。

垂直分区(Vertical Partitioning)这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。


五、MYSQL缓存配置

在MySQL中有多种多样的缓存,有的缓存负责缓存查询语句,也有的负责缓存查询数据。这些缓存内容客户端无法操作,是由server端来维护的。它会随着你查询与修改等相应不同操作进行不断更新。通过其配置文件我们可以看到在MySQL中的缓存:

  在这里主要分析query cache,它是主要用来缓存查询数据。当你想使用该cache,必须把query_cache_size大小设置为非0。当设置大小为非0的时候,server会就会缓存每次查询返回的结果,到下次相同查询server就直接从缓存获取数据,而不是再执行查询。能缓存的数据量就和你的size大小设置有关,所以当你设置的足够大,数据可以完全缓存到内存,速度就会非常之快。

  但是,query cache也有它的弊端。当你对数据表做任何的更新操作(update/insert/delete)等操作,server为了保证缓存与数据库的一致性,会强制刷新缓存数据,导致缓存数据全部失效。所以,当一个表格的更新数据表操作非常多的话,query cache是不会起到查询提升的性能,还会影响其他操作的性能。




Table类:自定义字段搜索的条件匹配方式

示例一、字段的精确匹配方式设置

默认情况下以下的搜索方式为模糊匹配,那么如果设置搜索5就显示5的记录呢

如何设置精准搜索输入就出不能模糊搜索

1、以demo模块为例的类文件是:dayrui/App/Demo/Controllers/Admin/Home.php

2、设置以下参数即可

$this->init['field']['title']['iswhere'] = 1;

表示title字段精确匹配

{xunruicms_img_title}


示例二:按整数模式匹配字段

1、以demo模块为例的类文件是:dayrui/App/Demo/Controllers/Admin/Home.php

2、设置以下参数即可

$this->init['field']['title']['isint'] = 1;

表示title字段按整数来匹配


网站表单/全局表单参数设置

每个网站表单都可以定义一种个性配置,为网站表单属性增加各种配置选项


例如,为test表单,增加文本选项appid参数设置


1、新建模板dayrui/App/Form/Views/diy_test.html


    appid
    
        
    

注意表单name的命名一定要是:data[setting][新的名称]



3、然后进入网站表单管理,找到test表单

{xunruicms_img_title}


4、找到test表单,点击修改,切换到自定义设置,就可以看到了

{xunruicms_img_title}


5、读取这些参数的方式

程序中读取:

当前表单控制器中时: $this->form['setting']['字段名']


开发者可以利用此方法为表单设置不同的属性参数,便于对表单个性二次开发存储值。




自动加载配置文件

自动加载使用场景,当你在config目录或者其他目录定义了一个数组类型的配置文件

例如,config/aaa.php

 'v1',
    'key2' => 'v2',
    'key3' => 'v3'
];


可以采用此方法来加载他并赋值给变量

$data = \Phpcmf\Service::R(WEBPATH . 'config/aaa.php');


语法是:

$data = \Phpcmf\Service::R(文件路径);


重写模块的系统Control控制器类方法

Control是控制器类继承的父类程序文件,由模块控制器继承。

一、后台控制器父类目录:/dayrui/App/Module/Control/Admin

用于模块的后台控制器,由模块目录的Admin控制器所继承

例如:Demo模块的后台控制器目录(/dayrui/App/Demo/Controllers/Admin)都是继承目录(/dayrui/App/Module/Control/Admin

当需要修改/dayrui/App/Demo/Controllers/Admin/Home.php时,可以打开这个控制器文件,定位到他的父控制器文件

{xunruicms_img_title}

如上图,那么他的父控制器就是 /dayrui/App/Module/Control/Admin/Module.php

在子控制器文件中可以对父控制器的函数方法进行重写,重开发,这样可以不影响主程序的升级。



二、前端控制器父类目录:/dayrui/App/Module/Control/Home

用于模块的前端控制器,由模块目录的Home控制器所继承

二次开发可以参考上面的流程类似。


三、会员中心控制器父类目录:/dayrui/App/Module/Control/Member

http://www.xunruicms.com/doc/924.html


Table类:搜索条件的开发

适用于继承table类的控制器文件,需要精通php的开发者

功能介绍:在列表搜索时,默认的搜索方式是模糊匹配,比如我需要改成以空格为分隔进行多词语搜索

{xunruicms_img_title}

默认情况下会将【词语一 词语二】当成一个词语进行数据库查询搜索。

现在,我们需要将他按空格分成两个词语分别进行模糊查询,当包含其中某一个词语时就表示搜索成功。


用法说明:

1、打开内容模块列表控制器

/dayrui/App/Demo/Controllers/Admin/Home.php

2、为主题字段加上自定义搜索函数

init['field']['title']['myfunc'] = 'mytitlewhere'; // 这是我增加的
      $this->_Admin_List();
   }


3、打开文件config/costom.php中定义这个函数:mytitlewhere

function mytitlewhere($param) {

    $rt = [];
    $arr = explode(' ', $param['keyword']);
    if ($arr) {
        foreach ($arr as $t) {
            $rt[] = $param['field'].' LIKE "%'.$t.'%"';
        }
    }

    return $rt ? implode(' OR ', $rt) : '';
}

这个函是将字符拆分成多个词语进行OR匹配



Fcms目录主控制器二次开发

/dayrui/Fcms/Control/目录是系统主核心文件,里面的文件是不能修改的,私自修改可能会引起系统不稳定导致系统崩溃,修改后不能对cms进行升级。

如果非要修改某些控制器怎么办?

我们以【admin.php?c=Linkage&m=index】为例,他对应的控制器文件是:/dayrui/Fcms/Control/Admin/Linkage.php,中的index()函数。

开发原理:复制控制器到app目录去,对应的url也需要改一下


1、创建一个空白应用插件,或者使用开发者工具创建,例如My插件目录

https://www.xunruicms.com/doc/573.html

2、把/dayrui/Fcms/Control/Admin/Linkage.php复制到 /dayrui/App/My/Controllers/Admin/Linkage.php

3、再打开新文件,修改顶部信息

改为


4、新地址改为:

index.php?s=my&c=Linkage&m=index

5、然后新的文件,你就可以随意进行二次开发写代码了,通过此方法,不会对cms内核破坏!


图片验证码验证开发

图形验证码开发流程,在网页端form体内加入图片验证码,提交之前进行图片验证码验证,可以有效的拦截垃圾消息。


开发思路:

1、用户输入系统生成的验证码字符串

2、提交后台进行字符串对比,相同表示验证成功


实现流程:

1、在form体内增加验证码函数图片和输入框代码,输入框name=code(验证时需要这个名称)



    {dr_code(120, 35)}


2、在PHP控制器中判断对比验证码,填写(1)中的name值的名称code

if (!\Phpcmf\Service::L('Form')->check_captcha('code')) {
    $this->_json(0, dr_lang('图片验证码不正确'), ['field' => 'code']);
}

此方法验证成功后就会销毁验证码,如果不想销毁验证码可以使用这个方法:

if (!\Phpcmf\Service::L('Form')->check_captcha_value($_POST['code'])) {
    $this->_json(0, dr_lang('图片验证码不正确'), ['field' => 'code']);
}

这种不销毁的验证方法,验证码有效期为5分钟,过期自动销毁

Table类:发布格式化保存数据

适用于继承table类的控制器文件,需要精通php的开发者

功能介绍:发布或修改内容入库之前进行格式化字段,比如发布或修改内容时,给title字段加一个随机字符

{xunruicms_img_title}


用法说明:

1、打开内容模块发布控制器

/dayrui/App/Demo/Controllers/Admin/Home.php

在类中增加:

    // 格式化保存数据 保存之前
    protected function _Format_Data($id, $data, $old) {

        $data = parent::_Format_Data($id, $data, $old);
        if (!$id) {
            // 表示新增数据
            
        } else {
            // 表示修改
        }
        $data['title'].=  "这是新增自动加的值";

        return $data;
    }


2、发布内容之后就会发现title字段加上了新值。


寻找自定义字段控制文件

通过宸逸自定义字段系统,开发者可以创建各种的字段输入控件,例如:

{xunruicms_img_title}

内容发布或在修改界面就可以展示出各种形态的字段输入样式,例如:

{xunruicms_img_title}


二次开发中研究这些字段空间是如何输出到界面上的,他在程序里面是如何控制的,那么就必须要找到这些字段控件的程序文件是哪一个;

例如,图一中的Text类型字段,我们就找到他的定义文件是哪一个。

1、找到文件夹 /dayrui/Fcms/Field

2、找到里面的字母文件Text.php,这个文件就是它了


-------如果在二次开发的场景中,需要对这些字段文件修改里面的内容,原则上Fcms目录里面全部文件是不允许修改的,否则影响版本的升级;

我们提供继承的方式来修改本文文件,就是复制到my目录再修改,这样就不会影响系统了,具体方法参考:

https://www.xunruicms.com/doc/734.html


Table操作类-列表右侧链接和底部按钮写法

右侧链接位置:

Table操作类-列表右侧链接和底部按钮写法

底部按钮位置:

Table操作类-列表右侧链接和底部按钮写法


实现原理:

在_List()方法之后,赋值$this->mytable数组,格式如下:

$this->mytable = [
            'foot_tpl' => '', // 底部按钮字符串
            'link_tpl' => '', // 右侧链接字符串
            'link_var' => 'html = html.replace(/\{id\}/g, row.id);html = html.replace(/\{id\}/g, row.id);', // 右侧链接的js变量替换,例如{id}表示id,可以写多组js赋值
        ];

赋值完毕后,传入到模板解析:

\Phpcmf\Service::V()->assign([
            'mytable' => $this->mytable,
        ]);

最终效果代码:

Table操作类-列表右侧链接和底部按钮写法


右侧链接示例代码:
$this->mytable = [
 'foot_tpl' => '', // 底部按钮字符串
 'link_tpl' => '', // 右侧侧链接字符串
 'link_var' => 'html = html.replace(/\{id\}/g, row.id);', // 侧链接的js变量替换,例如{id}表示id
];

// 侧链接,加一个a标签链接
$this->mytable['link_tpl'].= '';

\Phpcmf\Service::V()->assign([
 'mytable' => $this->mytable,
]);

底部按钮示例代码:

$this->mytable = [
'foot_tpl' => '', // 底部按钮字符串
'link_tpl' => '', // 右侧链接字符串
'link_var' => 'html = html.replace(/\{id\}/g, row.id);', // 右侧链接的js变量替换,例如{id}表示id
];

// 底部按钮

// 加入多选框按钮
$this->mytable['foot_tpl'].= '';
// 加入删除按钮
$this->mytable['foot_tpl'].= '';
// 加入新的按钮
$this->mytable['foot_tpl'].= '
'; \Phpcmf\Service::V()->assign([ 'mytable' => $this->mytable, ]);

Table类:外部数据库

适用于继承table类的控制器文件,需要精通php的开发者


功能介绍:查询其他数据库的表数据进行table操作


实现步骤:

1、定义外部数据库

https://www.xunruicms.com/doc/965.html

 'localhost',
    'username' => 'root',
    'password' => 'root',
    'database' => 'cms',
    'DBPrefix' => 'dr_',
];

// 这个cms2是站外的数据库信息
$db['cms2']    = [
    'hostname' => '192.168.2.12',
    'username' => 'root',
    'password' => 'root',
    'database' => 'cms2',
    'DBPrefix' => 'dede_',
];


2、Table控制器,新增识别外部库变量,上面配置是cms2

//其他与table控制器参数一样就行
        $this->_init([            "db_source" => "cms2",// 只需要加这句话,表示这个库
            'table' => '外部数据表名称', // (不带前缀的)表名字
            'field' => $field, // 可查询的字段
            'order_by' => 'id desc', // 列表排序,默认的排序方式
            'date_field' => '', // 按时间段搜索字段,没有时间字段留空
        ]);


配置属性获取方式

网站信息属性获取:

$cache = \Phpcmf\Service::L('cache')->get('site', SITE_ID);


模块配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID."-"."填写模块英文名");


全局表单配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('form-'.SITE_ID, "填写表单英文名");
表单名称: $cache['name']
表单seo标题:$cache['setting']['seo']['title']


模块表单配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID."-"."填写模块英文名", "form", "表单英文名");


评论插件-模块 配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('app-comment-'.SITE_ID, 'module', "模块目录"));


评论插件-模块表单 配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('app-comment-'.SITE_ID, 'mform', "模块目录-表单名"));


评论插件-全局表单 配置属性获取:

$cache = \Phpcmf\Service::L('cache')->get('app-comment-'.SITE_ID, 'form', "表单名"));


用户设置属性获取:

$cache = \Phpcmf\Service::C()->member_cache;

Table类:格式化结果集

针对列表查询结果集进行格式化处理,将默认的查询结果,进行自定义数据处理

在Table的控制器中进行定义:

    /**
     * 回调结果集
     * */
    protected function _Call_List($data) {
        return $data; // 这里的data就是列表页面查询的数组格式
    }

例如把结果集中的title字段 后面加一个字符



    /**
     * 回调结果集
     * */
    protected function _Call_List($data) {
        
        if ($data) {
            foreach ($data as $i => $t) {
                $data[$i]['title'].= '后面加一个字符串了';
            }
        }
        
        return $data;
    }


那么结果就是这样了

Table类:格式化结果集

Table类:自定义查询语句

适用于继承table类的控制器文件,需要精通php的开发者,需要v4.6.2及其以上版本支持


功能介绍:对数据库查询条件的扩展,比如自定义多个where条件,自定义多个join关联表等等


用法说明:

$this->_init([
            'table' => 'member', // 表的名字
            'field' => [], // 设置入库字段
            'show_field' => 'title', // 表的主字段
            'order_by' => 'member.id desc', // 列表排序显示方式
            'select_function' => function(&$select) {
                $select->join('member_data', 'member.id=member_data.id', 'left'); // 例如关联表查询
            }
]);
list($tpl) = $this->_List(); // 完成table自动查询并分页显示动作