《HongCMS开发者手册》--二次开发指南
模板语法参阅:/bbs/?thread-index-fid-1-tid-19.htm
一、前言:
说实在的,很怕写文档,特别是这种开发文档,无法知道别人需要什么样或者说什么程度的描述,自己高兴的事别人未必开心。所以,这个文档总的想法是将重点介绍清楚,让用户了解系统脉络,细枝末节的技术google就行了。
前些日子因参与其它公司的项目,研究了些PHP开发框架,如CI, ThinkPHP等这些,觉得这些小型框架对我来说很不爽,因为本人一直
喜欢4S的开发理念,即:Safe, Simple, Small, Stable (安全,简单,小巧,稳定),不刻意追求大而全的东西,认为简单是最美的。
这和性格有关,也很难改变。就拿CI来说吧,前台游客只要一进入网站,就有至少1个数据库
一、前言:
说实在的,很怕写文档,特别是这种开发文档,无法知道别人需要什么样或者说什么程度的描述,自己高兴的事别人未必开心。所以,这个文档总的想法是将重点介绍清楚,让用户了解系统脉络,细枝末节的技术google就行了。
前些日子因参与其它公司的项目,研究了些PHP开发框架,如CI, ThinkPHP等这些,觉得这些小型框架对我来说很不爽,因为本人一直
喜欢4S的开发理念,即:Safe, Simple, Small, Stable (安全,简单,小巧,稳定),不刻意追求大而全的东西,认为简单是最美的。
这和性格有关,也很难改变。就拿CI来说吧,前台游客只要一进入网站,就有至少1个数据库
写入及1个session生成,一个session在服务器就要写入一个文件,试想如果网站同时来了1万个用户访问,文件IO开销巨大,说得不好听点,服务器可能就死球了。对于框架,业内一直有这么一句话:学之者生,用之者死。本人觉得这句话很值得琢磨一下。
如今没有几个公司不要求程序员有MVC的开发理念,MVC确实有好处,本人也喜欢,但也不去刻意追求. 当然也有反对MVC的, mvc实例包括PHP创始人。HongCMS开发中有V和C,M基本没有,因为不需要或者说使用M编程反而累了,但完全可以使用Model,系统框架已经为它设计好了,程序包models/目录下有实例。特别是后台admin/models/目录下的admin.php, 它就是后台用户(管理员)的模型。说白了,模型就是一些类啦。
HongCMS系统框架APP.php非常小巧,仅5K大小,再加上XTpl超小模板引擎,HongCMS核心非常小巧、快速和高效。有基础的朋友,如果对HongCMS进行二次开发,或是参考其中的理念,足可以开发出大型系统来。
这些思想,加上多年做双语企业网站的经验,同时有朋友要我开发一个中英双语的小型企业
如今没有几个公司不要求程序员有MVC的开发理念,MVC确实有好处,本人也喜欢,但也不去刻意追求. 当然也有反对MVC的, mvc实例包括PHP创始人。HongCMS开发中有V和C,M基本没有,因为不需要或者说使用M编程反而累了,但完全可以使用Model,系统框架已经为它设计好了,程序包models/目录下有实例。特别是后台admin/models/目录下的admin.php, 它就是后台用户(管理员)的模型。说白了,模型就是一些类啦。
HongCMS系统框架APP.php非常小巧,仅5K大小,再加上XTpl超小模板引擎,HongCMS核心非常小巧、快速和高效。有基础的朋友,如果对HongCMS进行二次开发,或是参考其中的理念,足可以开发出大型系统来。
这些思想,加上多年做双语企业网站的经验,同时有朋友要我开发一个中英双语的小型企业
网站,于是HongCMS出生了。对于一些从事网站开发的朋友来说,我想HongCMS更适合成为你的工具,像很多使用weenCompany的用户能赚钱一样,使用HongCMS当然能赚钱,同时在技术上会有更大的提高。对于一般用户,HongCMS是中英文网站系统,对于懂程序的朋友来说,它是小型开发框架,开发由你。
二、目录布局与重要文件介绍
1. 根目录下的几个文件
.htaccess: 此文件是apache服务器下的伪静态规则文件,另外此文件还限制了浏览器可以访问或进入哪个目录或文件夹,增强了系统安全性。如果你添加了一个目录如blog,这个目录下独立安装了另一个blog系统,那么需要修改htaccess文件,以便允许浏览器访问blog目录。
index.php: HongCMS是单入口系统,所有前台页面的访问均从index.php进入。
二、目录布局与重要文件介绍
1. 根目录下的几个文件
.htaccess: 此文件是apache服务器下的伪静态规则文件,另外此文件还限制了浏览器可以访问或进入哪个目录或文件夹,增强了系统安全性。如果你添加了一个目录如blog,这个目录下独立安装了另一个blog系统,那么需要修改htaccess文件,以便允许浏览器访问blog目录。
index.php: HongCMS是单入口系统,所有前台页面的访问均从index.php进入。
: 此文件列举了一些目录,禁止SEO进入。基本上HongCMS除index.php文件夹都不希望SEO进入,因为SEO在其它目录或文件上抓不到有用的信息,但如果进入的话,反而可能会增加网站负担。
2. Admin目录: 后台管理目录, 里面存放的是后台管理入口文件,控制器和模型,也就是说,基本上后台管理的功能由其中的文件来完成。3.0.0版本开始, 后台管理有自己独立的入口文件index.php,同时后台管理目录可以任意修改。后台管理相当于一个独立的模块。
3. Cache目录: 此目录动态保存模板的缓存文件,一般不需要手动管理其中的文件。
4. Config目录: 系统配置目录,此目录下的config.php保存数据库连接信息等;settings.php保存网站基本设置信息,可以在后台管理中设置其中的信息,当然也可以手动直接修改其中的内容。
5. Controllers目录: 前台控制器文件目录,基本上前台的功能由此目录下的文件完成。
2. Admin目录: 后台管理目录, 里面存放的是后台管理入口文件,控制器和模型,也就是说,基本上后台管理的功能由其中的文件来完成。3.0.0版本开始, 后台管理有自己独立的入口文件index.php,同时后台管理目录可以任意修改。后台管理相当于一个独立的模块。
3. Cache目录: 此目录动态保存模板的缓存文件,一般不需要手动管理其中的文件。
4. Config目录: 系统配置目录,此目录下的config.php保存数据库连接信息等;settings.php保存网站基本设置信息,可以在后台管理中设置其中的信息,当然也可以手动直接修改其中的内容。
5. Controllers目录: 前台控制器文件目录,基本上前台的功能由此目录下的文件完成。
6. Images目录: 此目录为预留目录,在.htaccess中已经设置好了浏览器可以进入此目录,方便用户上传一些图片等,然后在文章内容中直接显示。
7. Includes目录: 此目录存放函数库文件或系统加载的核心文件,在core.php中对系统加载进行基本配置,functions.admin.php后台管理的函数库文件,functionsmon.php前台需要使用的函数库文件,functions.global.php里面是前后台都需要使用的函数库文件。
8. Install目录: 系统安装目录,在浏览器中进入此目录安装HongCMS。
9. Medels目录: 前台模型文件目录。
10. Public目录: 此目录存放前台模板文件,后台模板文件,前后台的JS文件等。
11. System目录: 系统框架核心目录,其中的backup目录用于保存后台管理中的数据库备份
文件,errors目录中是系统出错时显示的错误信息页面。plugins目录的是系统需要使用的一些类文件,如前后台的基础类文件,数据库类文件,JSON类文件,XTpl模板引擎类等等。system目录中的APP.php文件最重要,它是系统框架的核心类文件。可以这么说,系统的MVC开发模式由它确定。有兴趣的朋友可以仔细地分析一下此文件,有利于理解框架。
12. Uploads目录: 很明显,此目录将保存的是后台管理中各种上传文件,包括编辑器中上传的各种文件。
三、core.php系统加载配置核心文件
上面介绍了HongCMS为单入口网站系统,基本上所有的动态功能或动作均由根目录下的index.php文件引导完成。打开index.php文件,我们看到引入了includes/core.php,可见core.php文件在系统加载方面起作核心作用。
core.php需要仔细了解一下,其中最重要的是__autoload自动加载魔术函数,这个函数作用
12. Uploads目录: 很明显,此目录将保存的是后台管理中各种上传文件,包括编辑器中上传的各种文件。
三、core.php系统加载配置核心文件
上面介绍了HongCMS为单入口网站系统,基本上所有的动态功能或动作均由根目录下的index.php文件引导完成。打开index.php文件,我们看到引入了includes/core.php,可见core.php文件在系统加载方面起作核心作用。
core.php需要仔细了解一下,其中最重要的是__autoload自动加载魔术函数,这个函数作用
巨大,它允许实例化扩展类或模型类时,不需要在程序中加载相应的类文件,PHP服务器会自动加载相应的类文件,所以说它是魔术函数。这个自动加载函数主要是配合核心框架文件system/APP.php工作的。APP.php是核心框架文件,它的主要工作是对URL进行路由,简单地说就是把URL中的各种参数解释成相应的PHP程序文件去执行相关动作。APP.php文件的工作机制,有兴趣的朋友可以分析它,此文件很小仅5K,但它是框架的核心。
然后,在core.php文件中定义了一些前后台公共的常量,判断前台语言。再就是实例化数据库类,为后面的工作做准备。做二次开发的话,此文件一定要比较熟悉,因为它为系统加载运行做了最开始的一些准备工作。
四、URL路由及动作控制
APP.php核心框架文件的主要工作是解释URL中传递的各种参数到相应的程序中,然后由程序中的动作来完成相关功能,也就是说APP.php行使的路由功能。下面,我们来看几个具体的实例:
然后,在core.php文件中定义了一些前后台公共的常量,判断前台语言。再就是实例化数据库类,为后面的工作做准备。做二次开发的话,此文件一定要比较熟悉,因为它为系统加载运行做了最开始的一些准备工作。
四、URL路由及动作控制
APP.php核心框架文件的主要工作是解释URL中传递的各种参数到相应的程序中,然后由程序中的动作来完成相关功能,也就是说APP.php行使的路由功能。下面,我们来看几个具体的实例:
例1: / admin/ index.php / products / save
网址 / 模块 / 入口文件 / 控制器 / 动作
上例中,admin是指admin模块,HongCMS按模块来保存关联的程序,后台管理的控制器和模型程序放在admin目录下,我们称admin为后台模块。
products指示APP系统需要调用哪个控制器,由admin和products组合确定了需要加载admin/controllers/products.php文件,这是由APP.php框架决定的。打开admin/controllers/products.php文件,其中可以看到,这是一个类文件,类名为c_products,由SAdmin后台管理基类扩展而来。类名c_products中的"c_"表示它是一个控制器, 为什么不直接使用products作为类名呢?这是为了同模型类区分开来,以便APP框架能自动识别。控制器的类名做了如此约束后,模型类的类名就可以自由书写了,达到互不冲突的目的。这里SAdmin基类我们稍后介绍。
save指admin/controllers/products.php文件中的save()函数,这个函数来完成产品信息的保存功能,看似就像做了某个动作,不难理解。参数可以通过URL来传递,如 / admin / index.php / products / save / ?id=1, 也可以这样写 .... save?id=1,当然也可以传递多个参数。
例2:加载哪个控制器呢?
首先它肯定是访问根目录下的index.php文件,由于在URL中没有指定控制器和动作,APP框架默认解释为index / index,系统将加载根目录下controllers目录的index.php文件,并执行此文件中的index()函数,此函数显示首页的相关内容。也就是说,如果URL中未指定控制器时为index控制器,未指定动作时为index动作。
可以看出相当于: / index.php / index / index,如果希望APP完成默认的路由,必须由后至前的方式来省略书写URL。比如 / index.php / news就解释成了news控制器的index动作。
例2:加载哪个控制器呢?
首先它肯定是访问根目录下的index.php文件,由于在URL中没有指定控制器和动作,APP框架默认解释为index / index,系统将加载根目录下controllers目录的index.php文件,并执行此文件中的index()函数,此函数显示首页的相关内容。也就是说,如果URL中未指定控制器时为index控制器,未指定动作时为index动作。
可以看出相当于: / index.php / index / index,如果希望APP完成默认的路由,必须由后至前的方式来省略书写URL。比如 / index.php / news就解释成了news控制器的index动作。
五、伪静态及URL处理函数
现在的搜索引擎(SEO)已经非常厉害了,即使是动态页面也能很好地抓取其中的内容。当然伪静态更有利于SEO,同时URL也更简单。如上面/admin/index.php/products/save,开启了伪静态后,则可以写成:/admin/products/save。
有时用户的服务器或空间不支持伪静态,有时又支持,HongCMS后台基本设置中有一个开关,当服务器支持伪静态时,可以开启伪静态功能,不支持时可以关闭。那么我们在页面或程序里URL的写法就不能固定,需要随着伪静态功能的开关而相应变化。因而HongCMS默认有2个伪静态处理函数,前台URL()和后台BURL()。这2个函数分别保存在functions.global.php和functions.admin.php文件中。
以前台URL处理函数URL()为例,我们在程序中或模板页面中如何写URL呢?有了这个函数,可以说非常简单了。如上index.php/news/index如何写呢?前台PHP程序中这样写: UR
L('news'),index.php文件名肯定不需要写了(index动作也不需要写,因为没有指定动作时默认为index动作),URL()这个函数会根据伪静态是否开启自动加上index.php。传送参数也容易,如:URL('news/index?id=888&name=someone')
前台模板中如何调用URL函数呢?很简单,在需要显示URL的地方使用花括号(这是模板语法,请参阅: /bbs/?thread-index-fid-1-tid-19.htm)上例中,如果写在模板里,这样写:{echo URL('news/index?id=888&name=someone')}, 呵呵,echo输出并加一个花括号而已。
为了方便在模板文件中输出(显示)URL,系统前台函数库文件functionsmon.php有这么个函数PURL,P就是print的意思,意为直接输出URL。那么,在模板里,就这可以这样写URL:{PURL('news/index?id=888&name=someone')}
六、SAdmin后台基类和SWeb前台基类
这两个基类的类文件均保存在system/plugins/目录下,此目录下还有一些其它的类文件或插
前台模板中如何调用URL函数呢?很简单,在需要显示URL的地方使用花括号(这是模板语法,请参阅: /bbs/?thread-index-fid-1-tid-19.htm)上例中,如果写在模板里,这样写:{echo URL('news/index?id=888&name=someone')}, 呵呵,echo输出并加一个花括号而已。
为了方便在模板文件中输出(显示)URL,系统前台函数库文件functionsmon.php有这么个函数PURL,P就是print的意思,意为直接输出URL。那么,在模板里,就这可以这样写URL:{PURL('news/index?id=888&name=someone')}
六、SAdmin后台基类和SWeb前台基类
这两个基类的类文件均保存在system/plugins/目录下,此目录下还有一些其它的类文件或插
件,其中类的命名规则是必须是大写S开头(意思为系统类),这是为了让autoload自动加载函数能识别某个类是基础类(插件类)还是模型类。
admin目录下的后台控制器类都是由SAdmin后台基类继承而来,这样,在SAdmin基类中就可以完成一些后面管理页面中都需要的功能,比如页头、页尾、后台授权等。这个类因为是后台控制器的基类,所以需要做得尽可能的小。在SAdmin基类中,我们实例化了admin管理员用户模型,那么用户验证,权限,登录与退出等均由admin模型来完成,模型文件保存在: admin/models/admin.php
系统根目录下controllers目录保存的是前台控制器类,同理均由SWeb前台基类继承而来,但与SAdmin基类稍有不同。因为前台页面输出时都需要加载模板引擎,所以设计成SWeb基类由STpl模板引擎类继承而来,同时在SWeb基类中对STpl模板引擎类进行基本的设置,让其符合前台页面输出的要求,这样在编写前台控制器程序时就非常方便省事了。默认情况下,HongCMS系统前台是没有用户权限控制的,如果需要的话,前台的用户权限控制可以加在SWeb前台基类中。
admin目录下的后台控制器类都是由SAdmin后台基类继承而来,这样,在SAdmin基类中就可以完成一些后面管理页面中都需要的功能,比如页头、页尾、后台授权等。这个类因为是后台控制器的基类,所以需要做得尽可能的小。在SAdmin基类中,我们实例化了admin管理员用户模型,那么用户验证,权限,登录与退出等均由admin模型来完成,模型文件保存在: admin/models/admin.php
系统根目录下controllers目录保存的是前台控制器类,同理均由SWeb前台基类继承而来,但与SAdmin基类稍有不同。因为前台页面输出时都需要加载模板引擎,所以设计成SWeb基类由STpl模板引擎类继承而来,同时在SWeb基类中对STpl模板引擎类进行基本的设置,让其符合前台页面输出的要求,这样在编写前台控制器程序时就非常方便省事了。默认情况下,HongCMS系统前台是没有用户权限控制的,如果需要的话,前台的用户权限控制可以加在SWeb前台基类中。
总结一下,如果某些功能或者设置在前台或者后台总是出现,那么就要考虑将其代码写在SWeb前台或SAdmin后台两个基础类中,这是为了减少代码重复,提高程序效率。比如,前台的产品多级分类功能在所有的页面中均显示,那么我们就在SWeb前台基类中实现它,并将它的内容赋值给一个模板变量,在模板页面中调用就可以了。
如果我想给系统添加一个blog功能,该如何做呢?
给网站添加一个简单的blog功能,可以直接在controllers下添加一个blog控制器来实现。如果这个blog相当复杂, 也可以参考admin模块做一个独立的blog模块来实现。
七、后台Ajax介绍
首先说明一下,后台ajax同前台ajax稍有不同,这一节先说说后台ajax。在后台管理中,我们做ajax时不能输出页头,页尾,也不能输出数据库访问错误,因为这些信息返回后,js无法识别。同时,后台ajax也需要权限认证,否则是非法的,这几项都是基本要求。
一般地,后台ajax的URL这样写: BURL('language/ajax?action=delete'),看完上面的介绍后我们知道:language指控制器,也就是要执行admin/controllers/language.php程序文件;ajax指language控制器中的ajax动作。这样约定后,与控制器相关的ajax动作可以写到对应的控制器文件里,而不需要做一个独立的ajax文件,便于管理。如果某个控制器有多个ajax,我们可以通过参数action来确定执行哪个ajax。
打开system/plugins/SAdmin.class.php文件,我们看这个后台基类的构造函数,在这里决定了当动作名称为ajax时,禁止输出数据库错误,也不输出页头和页尾,同时实例化admin模型时加了一个参数$this->admin = new admin(1),这个1告诉admin模型,这是进行ajax操作,请做适合ajax相关的权限认证。打开admin/models/admin.php模型文件,可以看出在ajax授权时没有登录框的输出,只返回是否有权限的admin。
在SAdmin.class.php文件中,我们可以看出ajax返回三个变量的JSON数据:
$this->ajax['s'] s=status 表示ajax状态,1表示操作成功,0表示操作失败
$this->ajax['i'] i 指提示信息,ajax成功或失败都可以通过它返回一条信息
$this->ajax['d'] d 指实际返回的ajax数据,如果有数据的话,供后续的JS处理。
再打开public/admin/admin.js文件,我们对jquery的ajax做了一个简单的封装:ajax(url, send_data, callback)函数,了解ajax的朋友看一下就清楚了。
在后台管理中,使用ajax的地方相对还是较多的,特别是一些小功能的处理上,使用ajax后比较简单方便完成。打开admin/controllers/目录下的文件,搜索一下ajax,如果存在,说明这个控制器中有ajax操作,详细的使用请参照这些ajax代码,应该比较容易。
八、前台Ajax介绍
上一节中后台ajax是后台控制器中的ajax动作,而由于前台ajax不需要加载模板引擎,所以它不能是前台控制器的动作,因为前台控制器从SWeb基类扩展而来,并且自动加载了模板引擎。由于这些原因,我们将前台ajax做成控制器,它从SAjax系统扩展类中继承而来,也
$this->ajax['d'] d 指实际返回的ajax数据,如果有数据的话,供后续的JS处理。
再打开public/admin/admin.js文件,我们对jquery的ajax做了一个简单的封装:ajax(url, send_data, callback)函数,了解ajax的朋友看一下就清楚了。
在后台管理中,使用ajax的地方相对还是较多的,特别是一些小功能的处理上,使用ajax后比较简单方便完成。打开admin/controllers/目录下的文件,搜索一下ajax,如果存在,说明这个控制器中有ajax操作,详细的使用请参照这些ajax代码,应该比较容易。
八、前台Ajax介绍
上一节中后台ajax是后台控制器中的ajax动作,而由于前台ajax不需要加载模板引擎,所以它不能是前台控制器的动作,因为前台控制器从SWeb基类扩展而来,并且自动加载了模板引擎。由于这些原因,我们将前台ajax做成控制器,它从SAjax系统扩展类中继承而来,也
就是说我们为前台ajax独立写了一个基类SAjax,这个基本同SWeb基类相似,只是不需要加载模板引擎且去掉一些不必要的系统配置,满足ajax的需要就可以了。详细可参阅system/plugins/SAjax.php文件。
前台ajax既然是一个控制器,那么它的写法基本和前台其它控制器相似,只是它由SAjax扩展而来,详细看一下controllers/ajax.php文件。具体的ajax操作,由这个控制器的动作来完成。
前台ajax的URL可以这样写:PURL('ajax/delete?id=88'),它将执行ajax控制器中的delete函数。
HongCMS默认安装后,前台没有使用ajax,用户如果需要做前台ajax,可根据上面的介绍,并参考后台相关ajax的代码来写。
前台ajax既然是一个控制器,那么它的写法基本和前台其它控制器相似,只是它由SAjax扩展而来,详细看一下controllers/ajax.php文件。具体的ajax操作,由这个控制器的动作来完成。
前台ajax的URL可以这样写:PURL('ajax/delete?id=88'),它将执行ajax控制器中的delete函数。
HongCMS默认安装后,前台没有使用ajax,用户如果需要做前台ajax,可根据上面的介绍,并参考后台相关ajax的代码来写。
九、如何修改后台管理目录admin?
HongCMS安装后,后台管理目录为admin,建议修改成自己喜欢而别人不容易猜出的名称,以提高系统的安全性。
修改后台管理目录很容易,使用FTP工具直接修改admin文件夹的名称或者在未安装前手动修改。修改后还需要做以下工作:
1. 使用editplus,DW等工具打开根目录下的.htaccess文件
RewriteCond $1 !^(index\.php|public|uploads|install|images|admin|ajax\.php)
上面一行中的admin表示浏览器可直接进入admin目录,将admin替换成修改后的后台管理目录名称。
2. 同上打开根目录下的文件,将admin替换成修改后的后台管理目录名称。
HongCMS安装后,后台管理目录为admin,建议修改成自己喜欢而别人不容易猜出的名称,以提高系统的安全性。
修改后台管理目录很容易,使用FTP工具直接修改admin文件夹的名称或者在未安装前手动修改。修改后还需要做以下工作:
1. 使用editplus,DW等工具打开根目录下的.htaccess文件
RewriteCond $1 !^(index\.php|public|uploads|install|images|admin|ajax\.php)
上面一行中的admin表示浏览器可直接进入admin目录,将admin替换成修改后的后台管理目录名称。
2. 同上打开根目录下的文件,将admin替换成修改后的后台管理目录名称。
十、静态成员变量的调用(商业版)
HongCMS商业版3.2.0对核心框架(system/APP.php)做了小幅改进,即增加了几个静态成员变量,方便在程序或函数中调用,而不必再使用global方法。
打开APP.php文件,你将看到:
/**
* 当前控制器对象, 静态成员对象
* @var object
*/
public static $C; //调用时注意是大写C
/**
* 数据库访问对象, 静态成员对象
* @var object
HongCMS商业版3.2.0对核心框架(system/APP.php)做了小幅改进,即增加了几个静态成员变量,方便在程序或函数中调用,而不必再使用global方法。
打开APP.php文件,你将看到:
/**
* 当前控制器对象, 静态成员对象
* @var object
*/
public static $C; //调用时注意是大写C
/**
* 数据库访问对象, 静态成员对象
* @var object
*/
public static $DB;
/**
* 系统设置数组, 静态成员数组
* @var array
*/
public static $_CFG;
也就是说核心框架类文件中增加了三个静态成员:APP:C、APP:DB、APP:_CFG,下面我们说说这三个静态成员。APP:DB、APP:_CFG在core.php系统核心文件中进行了赋值,分别表示数据库访问对象和系统设置数组,那么在includes/functionsmon.php文件中的函数内调用数据库访问类或系统设置数组时,就可以这样写:
function xxxx(){
public static $DB;
/**
* 系统设置数组, 静态成员数组
* @var array
*/
public static $_CFG;
也就是说核心框架类文件中增加了三个静态成员:APP:C、APP:DB、APP:_CFG,下面我们说说这三个静态成员。APP:DB、APP:_CFG在core.php系统核心文件中进行了赋值,分别表示数据库访问对象和系统设置数组,那么在includes/functionsmon.php文件中的函数内调用数据库访问类或系统设置数组时,就可以这样写:
function xxxx(){
APP:DB->getOne(........);
$xxx = APP:_CFG['siteTimezone'];
}
虽然在core.php定义了全局的$DB对象,$_CFG数组,如果不改进APP.php, 那么上面这个函数需要这样写:
function xxxx(){
global $DB, $_CFG;
$DB->getOne(........);
$xxx = $_CFG['siteTimezone'];
}
$xxx = APP:_CFG['siteTimezone'];
}
虽然在core.php定义了全局的$DB对象,$_CFG数组,如果不改进APP.php, 那么上面这个函数需要这样写:
function xxxx(){
global $DB, $_CFG;
$DB->getOne(........);
$xxx = $_CFG['siteTimezone'];
}
接下来我们说说APP:C这个静态成员,它比较有意思。我们知道,HongCMS前台或后台的功能基本上由控制器来完成,即由controllers目录下的控制器文件来完成。
APP:C就是指当前这个控制器对象,根据上面几节的说明,我们知道前台的控制器类由SWeb基类扩展而来,而且SWeb基类又从模板类STpl类中扩展而来。现在打开includes/functionsmon.php文件,到Error函数,看看它是如何写的:
function Error($errors, $title = '', $time = 0) {
........
//设置类成员变量
APP:C->display_allowed = false; //错误发生时返回到前一个页面, 因此不允许加载其它的模板文件(只需要页头和页尾)
APP:C->system_info = ".....";
APP:C->assign('system_info', APP:C->system_info);
function Error($errors, $title = '', $time = 0) {
........
//设置类成员变量
APP:C->display_allowed = false; //错误发生时返回到前一个页面, 因此不允许加载其它的模板文件(只需要页头和页尾)
APP:C->system_info = ".....";
APP:C->assign('system_info', APP:C->system_info);
........
}
display_allowed, system_info是SWeb类的成员变量,assign是STpl类的成员函数,上面的代码表明:在公共的函数库中能方便地调用控制器的成员变量和成员函数。
商业版3.2.0对系统核心框架APP.php这个细小的改进,让程序员更加方便和灵活地编写需要的程序代码。改动虽小,改进很大。
十一、写什么呢?欢迎提出建议
HongCMS模板语法详细说明
HongCMS使用XTpl模板引擎,由于XTpl可以独立应用于其它的系统,所以这里比较详细的
介绍其使用方法。HongCMS用户仅需要看第一节的4、5两点和第二节就可以了。
XTpl模板引擎特点:
小巧强大, 速度快, 效率高(仅一个类文件, 含注释5K)
简单易学, 没有像书一样的开发文档
支持原生PHP代码, 模板代码书写规范易记
系统要求PHP5.0或以上版本
一、使用
1. 加载XTpl类文件
include(XTpl.class.php); //包含XTpl模板引擎核心类文件, 如果使用__autoload魔术函数, 这一步都可省略, 参照index.php文件
2. 实例化
普通方法: $tpl = new XTpl;
XTpl模板引擎特点:
小巧强大, 速度快, 效率高(仅一个类文件, 含注释5K)
简单易学, 没有像书一样的开发文档
支持原生PHP代码, 模板代码书写规范易记
系统要求PHP5.0或以上版本
一、使用
1. 加载XTpl类文件
include(XTpl.class.php); //包含XTpl模板引擎核心类文件, 如果使用__autoload魔术函数, 这一步都可省略, 参照index.php文件
2. 实例化
普通方法: $tpl = new XTpl;
扩展方法: class index extends XTpl{ ... } //也就是你的系统中的类从XTpl类中扩展而来, 这样符合MVC开发模式, 示例index.php就是这样做的
3. 初始化
普通实例化时的初始化:
$tpl->tpl_compile_dir = ROOT . 'cache/default/'; //定义模板缓存路径: cache缓存目录, default为当前模板
$tpl->tpl_template_dir = ROOT . 'templates/default/'; //定义当前模板路径: templates为模板目录, default为当前模板
$tpl->tpl_safe_mode = false; //XTpl类中,此项默认为false, 如果为true, 那么模板文件中写入的PHP代码将被注释而不会运行
$tpl->tpl_check = true; //XTpl类中,此项默认为true, 这个需要特别说明一下:
此项设置默认为true, 意思是加载模板时将检查此文件是否已经更新, 如果更新了就重新生成缓存, 如果未更新就直接读缓存, 这种情况适合网站开发初期
因为检查文件是否更新了, 比较消耗系统资源, 所以可以在系统开发完成后关闭此功能, 也就是设置为false
当设置为false时, 模板如果更新了, 此时需要清空缓存才能显示修改后的结果, 后面再说明tpl_remove_cache()清空缓存函数
扩展实例化时的初始化:
$this->tpl_compile_dir = ROOT . 'cache/default/';
$this->tpl_template_dir = ROOT . 'templates/default/';
.....
4. 分配变量到模板文件(以下均以扩展实例化XTpl为例)
因为检查文件是否更新了, 比较消耗系统资源, 所以可以在系统开发完成后关闭此功能, 也就是设置为false
当设置为false时, 模板如果更新了, 此时需要清空缓存才能显示修改后的结果, 后面再说明tpl_remove_cache()清空缓存函数
扩展实例化时的初始化:
$this->tpl_compile_dir = ROOT . 'cache/default/';
$this->tpl_template_dir = ROOT . 'templates/default/';
.....
4. 分配变量到模板文件(以下均以扩展实例化XTpl为例)
//一个数组
$arr = array(
'key1'=>'value1',
'key2' => 'value2'
);
$this->assign('test', 'a test var.'); //分配单个变量, 模板中这样调用: {$test}
$this->assign($arr); //同时分配多个变量, 模板中这样调用:{$key1}或{$key2}
$this->assign('arr', $arr); //分配数组, 模板中这样调用: {$arr['key1']} {$arr.key1} 或 使用for或foreach循环来显示
$someone = new someone(); //一个对象
$this->assign('obj', $someone); //分配对象, 模板中这样调用对象成员变量或函数: {$obj->myname}或{$obj->showname('aaaa')}
$arr = array(
'key1'=>'value1',
'key2' => 'value2'
);
$this->assign('test', 'a test var.'); //分配单个变量, 模板中这样调用: {$test}
$this->assign($arr); //同时分配多个变量, 模板中这样调用:{$key1}或{$key2}
$this->assign('arr', $arr); //分配数组, 模板中这样调用: {$arr['key1']} {$arr.key1} 或 使用for或foreach循环来显示
$someone = new someone(); //一个对象
$this->assign('obj', $someone); //分配对象, 模板中这样调用对象成员变量或函数: {$obj->myname}或{$obj->showname('aaaa')}
5. 加载模板文件
$this->display('index.tpl'); //加载模板文件, 支持下级目录, 如: $this->display('dirname/xxxx.tpl'); dirname表示当前模板目录下的二级目录
6. 清空缓存
上面说了, 当tpl_check设置为false时, 如果修改了模板文件, 那么需要清空缓存才能显示修改后效果
XTpl.class.php文件中也为你做好了一上独立的清空缓存函数tpl_remove_cache(), 它不依赖于XTpl类, 但XTpl类中使用了它(改函数名称时注意)
如果已经实例化了模板对象, 清空当前模板的缓存很容易:
$tpl->clear_compiled_tpl(); 或 $this->clear_compiled_tpl();
有些网站系统后台管理往往不使用模板引擎, 那么可以将XTpl.class.php中的tpl_remove_c
ache()函数复制到系统的函数库中, 这样运行:
tpl_remove_cache(ROOT . 'cache/default/'); //将当前模板路径作为参数
建议不要这样做: tpl_remove_cache(ROOT . 'cache/'); 否则将整个cache目录删除了
二、模板语法(模板文件编码规范)
1. 注释的写法两种:
标准(推荐): <!--注释的写法1-->
或: {*注释的写法2*}
注意: 如果在模板中插入了PHP代码, 那么PHP代码中不能按上述两种方式写注释, 而应该
tpl_remove_cache(ROOT . 'cache/default/'); //将当前模板路径作为参数
建议不要这样做: tpl_remove_cache(ROOT . 'cache/'); 否则将整个cache目录删除了
二、模板语法(模板文件编码规范)
1. 注释的写法两种:
标准(推荐): <!--注释的写法1-->
或: {*注释的写法2*}
注意: 如果在模板中插入了PHP代码, 那么PHP代码中不能按上述两种方式写注释, 而应该
按PHP规则写注释
2. 包含模板文件的写法:
写法1: {include "a.tpl"}或{include 'a.tpl'}{require a.tpl} //无引号, 单引号或双引号都行, 也可以混用
写法2: {include('a.tpl')}或{include ( 'a.tpl' ) } //使用括号
写法3: {require 'blog/a_b_c.tpl'} //注意, 当前模板目录下仅允许1级下级目录
注意:
i). 在任何模板文件中包含其它文件, 其路径都是相对于当前模板目录, 这一点不同于PHP, 需要注意
比如: 在blog/a_b_c.tpl文件中, 想包含blog/xxx.tpl文件, 不能写成{include "xxx.tpl"}, 而要
2. 包含模板文件的写法:
写法1: {include "a.tpl"}或{include 'a.tpl'}{require a.tpl} //无引号, 单引号或双引号都行, 也可以混用
写法2: {include('a.tpl')}或{include ( 'a.tpl' ) } //使用括号
写法3: {require 'blog/a_b_c.tpl'} //注意, 当前模板目录下仅允许1级下级目录
注意:
i). 在任何模板文件中包含其它文件, 其路径都是相对于当前模板目录, 这一点不同于PHP, 需要注意
比如: 在blog/a_b_c.tpl文件中, 想包含blog/xxx.tpl文件, 不能写成{include "xxx.tpl"}, 而要
写成: {include "blog/xxx.tpl"}
ii). include和require没有任何差别, 前面加@也无效. 这两种包含文件的方式完全是为了满足某些同学的习惯
iii). 如果不使用括号, include或require后面至少有一个空格.
Smarty, DZ等这样写{include file="a.tpl"}, 而XTpl的写法更简单, 同时更像PHP语法, 看完其它语法, 同学们将更有体会!!
模板中是否可以包含PHP文件呢? 当然可以, 但要使用PHP代码的方式, 如: <?php include('xxx.php'); ?> 那么此句中包含的文件是相对于当前运行的PHP文件
3. CSS或JS写法不受影响,但是两个花括号需要独立成行, 否则{}之间的代码当PHP模板代
ii). include和require没有任何差别, 前面加@也无效. 这两种包含文件的方式完全是为了满足某些同学的习惯
iii). 如果不使用括号, include或require后面至少有一个空格.
Smarty, DZ等这样写{include file="a.tpl"}, 而XTpl的写法更简单, 同时更像PHP语法, 看完其它语法, 同学们将更有体会!!
模板中是否可以包含PHP文件呢? 当然可以, 但要使用PHP代码的方式, 如: <?php include('xxx.php'); ?> 那么此句中包含的文件是相对于当前运行的PHP文件
3. CSS或JS写法不受影响,但是两个花括号需要独立成行, 否则{}之间的代码当PHP模板代
码解析了, 并且会出错!!! 晕菜.......
<script type="text/javascript">
function aaa(){
alert('aaa');
}
</script>
<style type="text/css">
body {
font:12px;
......
}
</style>
实在是不想分行, 有时确实需要在一行上编写js代码,那么可以在{后面加一个空格,如: fu
<script type="text/javascript">
function aaa(){
alert('aaa');
}
</script>
<style type="text/css">
body {
font:12px;
......
}
</style>
实在是不想分行, 有时确实需要在一行上编写js代码,那么可以在{后面加一个空格,如: fu
nction aaa(){ alert('haha')}, CSS同理。
如果不想分行又不能有空格该怎么办呢? 比如要输出:{今天的天气不错},那你只好把{}转换成ASCII码了。
4. 显示变量(模板中输出变量的内容)
简单显示: {$test} 注意{}内部不能有任何空格或其它的PHP运行符, 同时必须以$开头, 否则就变成赋值运算了
显示数组: {$arr["key1"]} 或 {$arr['key2']} 或 {$arr.key1} 或 {$arr.key2}
显示对象成员变量(->前后不能有空格): {$obj->myname}
显示对象成员函数运行返回值(->前后不能有空格): {$obj->showname('aaaa')}
如果不想分行又不能有空格该怎么办呢? 比如要输出:{今天的天气不错},那你只好把{}转换成ASCII码了。
4. 显示变量(模板中输出变量的内容)
简单显示: {$test} 注意{}内部不能有任何空格或其它的PHP运行符, 同时必须以$开头, 否则就变成赋值运算了
显示数组: {$arr["key1"]} 或 {$arr['key2']} 或 {$arr.key1} 或 {$arr.key2}
显示对象成员变量(->前后不能有空格): {$obj->myname}
显示对象成员函数运行返回值(->前后不能有空格): {$obj->showname('aaaa')}
显示系统常量: {echo ROOT} 注意不能写成这样: {ROOT}
显示运算后的结果: {echo intval($key + 1.2)} 注意不能写成这样: {intval($key + 1.2)}
能否{echo $test}或{print $test}这样显示变量呢? 当然可以, 只要你不怕累着, 呵呵.
5. 变量赋值及运算
简单赋值: {$key=3}
运算赋值: {$key = 3+6}
运算赋值: {$key = $key+6}
调用系统函数运算并赋值: {$key=intval($key+0.6)}
字符串运算: {$key=$key.'aaa' . 'bbb'}
赋值中使用对象成员变量或函数(->前后可以有空格): {$key=$obj -> myname .$obj -> showname('aaaa')}
调用系统常量运算: {$key = ROOT . 'abc/'}
XTpl模板中的赋值和运算, 几乎写PHP代码一样, 实在是太强了. 这样类似Smarty中的函数和修改器就完全没必要了
比较Smarty中cat修改器这样写: {$test|cat:'123'|cat: "456"}
调用系统函数运算并赋值: {$key=intval($key+0.6)}
字符串运算: {$key=$key.'aaa' . 'bbb'}
赋值中使用对象成员变量或函数(->前后可以有空格): {$key=$obj -> myname .$obj -> showname('aaaa')}
调用系统常量运算: {$key = ROOT . 'abc/'}
XTpl模板中的赋值和运算, 几乎写PHP代码一样, 实在是太强了. 这样类似Smarty中的函数和修改器就完全没必要了
比较Smarty中cat修改器这样写: {$test|cat:'123'|cat: "456"}
XTpl中这样写: {echo $test.'123'.'456'}
对比一下, 是不是更短更简单了, 再也不用记cat这样的修改器名称和用法了
再比如: 由于模板中的URL有时需要根据系统是否开启伪静态来切换, 这时系统中可以做一个URL($url)之类的函数:
function URL($url){
if('开启伪静态'){
return xxxx . $url;
}else{
return yyyy . $url;
}
}
那么在模板中可以这样写URL: {echo URL('blog/index')}
对比一下, 是不是更短更简单了, 再也不用记cat这样的修改器名称和用法了
再比如: 由于模板中的URL有时需要根据系统是否开启伪静态来切换, 这时系统中可以做一个URL($url)之类的函数:
function URL($url){
if('开启伪静态'){
return xxxx . $url;
}else{
return yyyy . $url;
}
}
那么在模板中可以这样写URL: {echo URL('blog/index')}
如果上面的URL函数中是echo输出(不建议), 那么可以直接这样写: {URL('blog/index')}
6. if elseif else语法同PHP, 只是需要/if结束:
{$var = 3} //赋值
{if $var=='1' || $var=='9'}
{$var}
{elseif($var=='2' AND $var != '9') OR $var==3}
{$var}
{else}
{$var}
{/if}
6. if elseif else语法同PHP, 只是需要/if结束:
{$var = 3} //赋值
{if $var=='1' || $var=='9'}
{$var}
{elseif($var=='2' AND $var != '9') OR $var==3}
{$var}
{else}
{$var}
{/if}
7. for和foreach循环语法同php, 只是需要/for或/foreach结束:
{for($i=1;$i<=8;$i++)}
{$i}
{/for}
<!--不要括号也可以, 但for后面需要有空格, foreach同理-->
{for $i=1; $i<=8; $i++}
{$i}
{/for}
{foreach($arr as $k=>$v)}
{$k}: {$v}
{/foreach}
{for($i=1;$i<=8;$i++)}
{$i}
{/for}
<!--不要括号也可以, 但for后面需要有空格, foreach同理-->
{for $i=1; $i<=8; $i++}
{$i}
{/for}
{foreach($arr as $k=>$v)}
{$k}: {$v}
{/foreach}
<!--二维或多维数组-->
{foreach($arr as $key=>$value)}
{$value.id} 或 {$value['id']}
{$value.item.item2} 或 {$value['item']['item2']}
{/foreach}
8. 直接使用PHP代码, 意味着你可以做PHP中的任何事:
<?php
//注意: php代码中的注释只能按PHP规则写
echo 'this is php codes';
$this->dothing();
?>
{foreach($arr as $key=>$value)}
{$value.id} 或 {$value['id']}
{$value.item.item2} 或 {$value['item']['item2']}
{/foreach}
8. 直接使用PHP代码, 意味着你可以做PHP中的任何事:
<?php
//注意: php代码中的注释只能按PHP规则写
echo 'this is php codes';
$this->dothing();
?>
9. 在模板文件中, 是否可以在模板代码中调用php代码中定义的变量呢?可以, 但是复杂一点点.
也就是说你可以使用PHP代码处理变量,然后用特定格式赋值,再在模板代码中调用. 比如处理环境变量等
<?php
//php代码语法可以按php规则书写,包括注释
$this->_tpl_vars['var_test'] = $_SERVER['HTTP_HOST'];
?>
模板代码中调用php变量: {$var_test}
10. 在模板文件中, PHP代码是否可以调用模板代码中的变量呢?可以, 但是复杂一点点.
{$aaa = array('a', 'b')} <!--前面是模板代码-->
<?php
echo '<pre>';
var_dump($this->_tpl_vars['aaa']); //这里是PHP代码
echo '</pre>';
?>
第9条和第10条说的就是PHP代码和模板代码之间交互, 注意这个东东$this->_tpl_vars的写法
10. 在模板文件中, PHP代码是否可以调用模板代码中的变量呢?可以, 但是复杂一点点.
{$aaa = array('a', 'b')} <!--前面是模板代码-->
<?php
echo '<pre>';
var_dump($this->_tpl_vars['aaa']); //这里是PHP代码
echo '</pre>';
?>
第9条和第10条说的就是PHP代码和模板代码之间交互, 注意这个东东$this->_tpl_vars的写法
就OK了.
无论你是用普通方法, 还是扩展方法实例化XTpl模板类, 都是这样写: $this->_tpl_vars, 这里的$this指的是模板对象
无论你是用普通方法, 还是扩展方法实例化XTpl模板类, 都是这样写: $this->_tpl_vars, 这里的$this指的是模板对象
WeLive4无法连接服务器的解决办法!
由于WeLive4是一个使用socket通讯技术的企业级系统, 能否正常使用,受各种服务器的设置, linux下iptables防火墙配置等影响比较大。
不同的服务器可能需要做相应的调整才能正常使用!!
我们的开发环境为: win7, PHPnow(apache php mysql)。本地服务器基本未做任何调整,均能正常安装与使用。
下面是其它类型的服务器出现的问题及相应解决办法:
不同的服务器可能需要做相应的调整才能正常使用!!
我们的开发环境为: win7, PHPnow(apache php mysql)。本地服务器基本未做任何调整,均能正常安装与使用。
下面是其它类型的服务器出现的问题及相应解决办法:
第一类服务器: IIS FastCGI服务器
FastCgi的配置文件“fcgiext.ini”(一般位于目录“C:/WINDOWS/system32/inetsrv”下, 确切位置自己探索下)
在“fcgiext.ini”最末php的配置内容中增加了一些参数,如下:
[Types]
php=PHP
[PHP]
ExePath=C:/
InstanceMaxRequests=10000
EnvironmentVars=PHP_FCGI_MAX_REQUESTS:10000
RequestTimeout=500 //用户连接时间限制(秒), 这个要改大,否则WeLive4连接中, 不发信息就会自动断线(按理说fastCGI不应该限制socket连接时间)
ActivityTimeout=900 //这个设置影响socket长时间保持运行, 这个要改成9999999,即
FastCgi的配置文件“fcgiext.ini”(一般位于目录“C:/WINDOWS/system32/inetsrv”下, 确切位置自己探索下)
在“fcgiext.ini”最末php的配置内容中增加了一些参数,如下:
[Types]
php=PHP
[PHP]
ExePath=C:/
InstanceMaxRequests=10000
EnvironmentVars=PHP_FCGI_MAX_REQUESTS:10000
RequestTimeout=500 //用户连接时间限制(秒), 这个要改大,否则WeLive4连接中, 不发信息就会自动断线(按理说fastCGI不应该限制socket连接时间)
ActivityTimeout=900 //这个设置影响socket长时间保持运行, 这个要改成9999999,即
很大。
也可以将上述两个设置直接删除, 然后重启服务器再测试WeLive
第二类服务器:LAMP apache服务器或LNMP fastCGI服务器:
建议检查服务器如下配置:
1. php配置中的safe_mode为off (如果为on, 肯定无法运行正常)
2. php配置中的disable_functions可禁止一些函数运行: set_time_limit, ignore_user_abort等函数不能禁用
3. SELinux是否disabled (如果SELinux没有设置成disabled, 还需要调整有关设置才能启动socket服务)
也可以将上述两个设置直接删除, 然后重启服务器再测试WeLive
第二类服务器:LAMP apache服务器或LNMP fastCGI服务器:
建议检查服务器如下配置:
1. php配置中的safe_mode为off (如果为on, 肯定无法运行正常)
2. php配置中的disable_functions可禁止一些函数运行: set_time_limit, ignore_user_abort等函数不能禁用
3. SELinux是否disabled (如果SELinux没有设置成disabled, 还需要调整有关设置才能启动socket服务)
4. 检查iptables防火墙是否开放了socket使用的端口号,比如开放8430给socket使用,那么此端口不能给其它服务使用,如被动的FTP服务。
同时在防火墙iptables配置文件中开放socket端口号时, 需要允许接受tcp和icmp两种协议的封包。
如果不知道如何配置iptables, 可以先关闭iptables服务进行测试,这样可先定位无法正常使用的原因:service iptables stop
5. 检查WeLive4基本设置中的socket端口号是否与第3点开放的端口号一致。
6. LNMP平台, 使用fastCGI加载php,检查fastCGI的配置文件中以下配置:
RequestTimeout=500 //用户连接时间限制(秒), 这个要改大,否则WeLive4连接中, 不发信息就会自动断线(按理说fastCGI不应该限制socket连接时间)
ActivityTimeout=900 //这个设置影响socket长时间保持运行, 这个要改成9999999,即很大。
同时在防火墙iptables配置文件中开放socket端口号时, 需要允许接受tcp和icmp两种协议的封包。
如果不知道如何配置iptables, 可以先关闭iptables服务进行测试,这样可先定位无法正常使用的原因:service iptables stop
5. 检查WeLive4基本设置中的socket端口号是否与第3点开放的端口号一致。
6. LNMP平台, 使用fastCGI加载php,检查fastCGI的配置文件中以下配置:
RequestTimeout=500 //用户连接时间限制(秒), 这个要改大,否则WeLive4连接中, 不发信息就会自动断线(按理说fastCGI不应该限制socket连接时间)
ActivityTimeout=900 //这个设置影响socket长时间保持运行, 这个要改成9999999,即很大。
IIS下的fastCGI有此两项设置,上两项供Nginx下fastCGI参考。
7. 配置等调整后,重启服务器,不是service httpd restart这种重启。是reboot计算机重启。
8. 问题还存在时,更改一下默认的端口号。在后台基本设置中改一下Socket默认端口号843,改成8430试下。有些用户这么改下,服务器连接成功。
可能的原因是某些服务器把843商品禁用了。
7. 配置等调整后,重启服务器,不是service httpd restart这种重启。是reboot计算机重启。
8. 问题还存在时,更改一下默认的端口号。在后台基本设置中改一下Socket默认端口号843,改成8430试下。有些用户这么改下,服务器连接成功。
可能的原因是某些服务器把843商品禁用了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论