PHPCMS

一、模版引擎

如:调用单页面index.php?m=content&c=index&a=lists&catid=9.
1.先获取到模版变量的值$template_list="list";然后通过$type!=0来判断是单页面,
   然后通过$template = $setting['page_template'] ? $setting['page_template'] : 'page';获取单页免的模版page.html.

2.引入模版include template('content',$template);

3.查看template()函数:定义在/phpcms/libs/functions/global.func.php.
  template($module = 'content', $template = 'index', $style = '');
  传入的三个参数分别是:
  (1)module;
  (2)模版,比如单页面page.html;
  (3)模版风格,就是/phpcms/templates/下面的目录名,比如default,che.
  该函数实现的功能:
  (1)通过file_exists($compiledtplfile):判断模版编译文件是否存在;
  (2)通过filemtime()判断模版文件的生成时间是否大于模版编译文件;
  以上两点如果(||连接)为真,则通过$template_cache->template_compile($module, $template, $style);编译模版文件;

4.查看template_compile()函数:定义在/phpcms/libs/classes/template_cache.class.php.
  template_compile($module, $template, $style = 'default');
  传入的三个参数分别是:
  (同上)
  该函数实现的功能:
  (1)通过$content = @file_get_contents ( $tplfile );读取模版源文件的内容;
  (2)通过$content = $this->template_parse($content);正则匹配替换掉标签,将标签替换为php代码:
  (3)通过$strlen = file_put_contents ( $compiledtplfile, $content );将替换后的字符串写入模版编译文件;
  (4)返回$strlen,即用include template('content',$template);将$strlen引入到控制器代码里。其本质就是php和html代码混编。

5.模版解析:通过template_parse($str)用正则替换标签。

    /**
* 解析模板
*
* @param $str 模板内容
* @return ture
*/
public function template_parse($str) {
$str = preg_replace ( "/\{template\s+(.+)\}/", "<?php include template(\\1); ?>", $str );
$str = preg_replace ( "/\{include\s+(.+)\}/", "<?php include \\1; ?>", $str );
$str = preg_replace ( "/\{php\s+(.+)\}/", "<?php \\1?>", $str );
$str = preg_replace ( "/\{if\s+(.+?)\}/", "<?php if(\\1) { ?>", $str );
$str = preg_replace ( "/\{else\}/", "<?php } else { ?>", $str );
$str = preg_replace ( "/\{elseif\s+(.+?)\}/", "<?php } elseif (\\1) { ?>", $str );
$str = preg_replace ( "/\{\/if\}/", "<?php } ?>", $str );
//for 循环
$str = preg_replace("/\{for\s+(.+?)\}/","<?php for(\\1) { ?>",$str);
$str = preg_replace("/\{\/for\}/","<?php } ?>",$str);
//++ --
$str = preg_replace("/\{\+\+(.+?)\}/","<?php ++\\1; ?>",$str);
$str = preg_replace("/\{\-\-(.+?)\}/","<?php ++\\1; ?>",$str);
$str = preg_replace("/\{(.+?)\+\+\}/","<?php \\1++; ?>",$str);
$str = preg_replace("/\{(.+?)\-\-\}/","<?php \\1--; ?>",$str);
$str = preg_replace ( "/\{loop\s+(\S+)\s+(\S+)\}/", "<?php \$n=1;if(is_array(\\1)) foreach(\\1 AS \\2) { ?>", $str );
$str = preg_replace ( "/\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}/", "<?php \$n=1; if(is_array(\\1)) foreach(\\1 AS \\2 => \\3) { ?>", $str );
$str = preg_replace ( "/\{\/loop\}/", "<?php \$n++;}unset(\$n); ?>", $str );
$str = preg_replace ( "/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/", "<?php echo \\1;?>", $str );
$str = preg_replace ( "/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/", "<?php echo \\1;?>", $str );
$str = preg_replace ( "/\{(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/", "<?php echo \\1;?>", $str );
$str = preg_replace("/\{(\\$[a-zA-Z0-9_\[\]\'\"\$\x7f-\xff]+)\}/es", "\$this->addquote('<?php echo \\1;?>')",$str);
$str = preg_replace ( "/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", "<?php echo \\1;?>", $str );
$str = preg_replace("/\{pc:(\w+)\s+([^}]+)\}/ie", "self::pc_tag('$1','$2', '$0')", $str);
$str = preg_replace("/\{\/pc\}/ie", "self::end_pc_tag()", $str);
$str = "<?php defined('IN_PHPCMS') or exit('No permission resources.'); ?>" . $str;
return $str;
}

关键点:1.\s 空格匹配的使用;
                 2.\1  \2分组的使用;
                 3.替换为self::pc_tag函数的使用。

二、框架实现思路(参考:http://www.tuicool.com/articles/BvU3i2v)
  通过单一入口的pc_base::create_app()来创建一个应用,调用不同的类库处理不同的应用;
      当处理application时:调用框架类库文件下的application.class.php文件,执行构造函数,加载param路由类,使用路由类中的$param->route_m(),$param->route_c(),$param->route_a()获取模块和控制器以及方法,route_m为模块,在modules文件下,然后是控制器和方法,标准的mvc结构。然后执行int函数,执行load_controller加载获取到的控制器并且实例化!

三、外部引用来调用phpcms的类库

include_once '../phpcms/base.php';//引入主文件
pc_base::load_sys_class('model', '', 0);//加载model类
class Api extends model {//继承model类,即调用model的各种数据库方法
public function __construct() {
$this->db_config = include "../config/database.php";//此处得包含进数据库配置文件
$this->db_setting = 'default';
//$this->table_name = 'admin';
parent::__construct();
}
}
$apiDb = new Api(); $adpos = isset($_GET['adpos'])&&!empty($_GET['adpos'])?$_GET['adpos']:"0";
if($adpos=="login"){
$spaceid = 25;
}elseif ($adpos=="register"){
$spaceid = 23;
}else{
$spaceid = 0;
} $sql = "SELECT s.width,s.height,p.setting FROM `u8_poster_space` s LEFT JOIN `u8_poster` p ON s.spaceid=p.spaceid WHERE p.spaceid=$spaceid"; $res = $apiDb->db->get_ones($sql);//根据sql语句获取一行结果集

四、数据库实现原理

1.三大类
 mysql.class.php 数据库实现类 :final class mysql;
 db_factory.class.php 数据库工厂类 :final class db_factory;
 model.class.php 数据模型基类 :class model。

2.实现流程(/phpcms/libs/class/)
  (1)mysql.class.php提供数据库连接、查询、执行等各种实现方法;

/**
* 真正开启数据库连接
*
* @return void
*/
public function connect() {
$func = $this->config['pconnect'] == 1 ? 'mysql_pconnect' : 'mysql_connect';
if(!$this->link = @$func($this->config['hostname'], $this->config['username'], $this->config['password'], 1)) {
$this->halt('Can not connect to MySQL server');
return false;
} if($this->version() > '4.1') {
$charset = isset($this->config['charset']) ? $this->config['charset'] : '';
$serverset = $charset ? "character_set_connection='$charset',character_set_results='$charset',character_set_client=binary" : '';
$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',')." sql_mode='' ") : '';
$serverset && mysql_query("SET $serverset", $this->link);
} if($this->config['database'] && !@mysql_select_db($this->config['database'], $this->link)) {
$this->halt('Cannot use database '.$this->config['database']);
return false;
}
$this->database = $this->config['database'];
return $this->link;
}

  (2)db_factory.class.php用get_instance($db_config = '')方法返回当前工厂类,用get_database($db_name)方法返回数据库操作实例(它调用工厂类的connect($db_name)来实现工厂类原理),

/**
* 加载数据库驱动
* @param $db_name 数据库配置名称
* @return object
*/
public function connect($db_name) {
$object = null;
switch($this->db_config[$db_name]['type']) {
case 'mysql' :
pc_base::load_sys_class('mysql', '', 0);
$object = new mysql();
break;
case 'mysqli' :
$object = pc_base::load_sys_class('mysqli');
break;
case 'access' :
$object = pc_base::load_sys_class('db_access');
break;
default :
pc_base::load_sys_class('mysql', '', 0);
$object = new mysql();
}
$object->open($this->db_config[$db_name]);
return $object;
}

  (3)model.class.php加载工厂类(pc_base::load_sys_class('db_factory', '', 0);),提供数据库的curd操作方法。

$this->db = db_factory::get_instance($this->db_config)->get_database($this->db_setting);//获取数据库实例

  总结:通过工厂类的get_instance()获取当前实例,调用工厂方法的get_database()连接数据库并返回数据库操作实例,并返回给model的$this->db,最后所有方法的调用直接通过$this->db调用model里的方法即可。

PHPCMS源码分析的更多相关文章

  1. phpcms 源码分析二:

    这次是逆雪寒的common.inc.php第二部分: <?php /* 明天放假了.今天在写点罗.放假没空写了.要陪老婆,大家看了有什么不明白的.可以跟帖问.我懂的我会回答.谢谢 [/php] ...

  2. phpcms 源码分析七: 模板引擎实现

    这次是逆雪寒对模板引擎实现的分析: 1 /* 函数 template函数是在global.func.php 里面定义的. 在前面的phpcms 的首页 index.php 里就见到了. 用法: inc ...

  3. phpcms 源码分析六:index文件

    这次是逆雪寒对index.php的分析: /* [/php] [ 本帖最后由 逆雪寒 于 2007-12-25 16:12 编辑 ] 尽量每天都有新的东西每天都能进一小步 现在开始讲 index.ph ...

  4. phpcms 源码分析五:文件缓存实现

    这次是逆雪寒的文件缓存实现代码分析: /* [/php] PHPCMS的文本缓存实现: [php] <?php /* 这个文件里面全是有关生成文本缓存的函数.文本缓存是个好东西.一般的项目,我们 ...

  5. phpcms 源码分析四: 数据库类实现

    这次是逆雪寒的数据库类分析: <?php /* 这个讲 phpcms 的数据库类 和 phpcms 的文本缓存的实现.看了看 都是很简单的东西.大家看着我注释慢慢看吧.慢慢理解,最好能装了PHP ...

  6. phpcms 源码分析三:common.inc.php

    这次是逆雪寒分析common.inc.php的数据库部分: <?php // 包含数据库操作类,下章详说 require PHPCMS_ROOT.'/include/'.$db_file.'.c ...

  7. phpcms 源码分析一: common.inc.php

      其实就是从网上找到的的逆雪寒的分析, 我下来之后发现格式和错字的问题,非常影响阅读,现在我就是做了下搬运工的角色, 同时将格式调整到可读性提高点而已,让各位看官稍微舒心点: 下面进入整体: < ...

  8. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  9. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

随机推荐

  1. Npm安装以及express框架的使用

    一.安装node.js 下载node.js,并将其放置合适的位置 二.修改环境变量 添加Node执行路径添加到系统的环境变量PATH中,如图:在PATH变量的值的最后添加“C:\Program Fil ...

  2. JAVA BigDecimal的相加

    之前很少使用这样的一个对象BigDecimal,今天在改需求的时候遇到了,结果坑爹的怎么相加最后都为零. 代码如下: BigDecimal totalAmount = new BigDecimal(0 ...

  3. android加密DESede/CBC/PKCS5Padding

    from://http://my.oschina.net/u/269082/blog/56163 工作中需要和HPH对接,接口一些敏感信息,讨论后用3DES加密,由于我做的android邮件客户端是依 ...

  4. WordPress主题开发实例:get_term_by()获取指定分类链接

    根据名称获取链接 <?php //根据名称获取对应的id $term=get_term_by('name','新闻动态','category'); $term_id=$term->term ...

  5. Linux学习7-tomcat部署多个项目(多个端口)

    前言 前面已经在tomcat上搭建了jenkins的环境,如果我们有多个项目需要部署的话,如何在一个tomcat下部署多个项目呢? 前面是直接在:8080/jenkins访问的,如果有其它项目部署的话 ...

  6. 在SpringMVC中使用Jackson并格式化时间

    在spring MVC 3中,要实现REST风格的JSON服务,最简单的方式是使用 @ResponseBody 注解.该注解会自动把返回的对象,序列化为JSON. 来看一个最简单的例子.这个例子先使用 ...

  7. SharePoint 取消分享时的默认发邮件

    前言 最近遇到一个需求,就是sharepoint默认分享的时候,会默认勾选发送邮件的功能.而用户,经常会用到分享的功能,但是不需要发送邮件,需要默认不勾选这个操作. 这样,就需要修改sharepoin ...

  8. 灵书妙探第八季/全集Castle迅雷下载

    英文全名Castle,第8季(2015)ABC.本季看点:<灵书妙探>讲述性格和背景迥异的两人在不断的斗嘴与摩擦中竟然渐渐培养出了默契,成了名符其实的最佳搭档.在上季Richard Cas ...

  9. versionCode溢出的问题

    android应用的版本主要由versionCode和versionName来决定,android系统是根据versionCode来验证新的apk是否能安装.如果已安装高版本的应用,就无法使用覆盖安装 ...

  10. IIS回收后首次访问慢问题

    禁用时间间隔回收 设置为0 然后设置指定时间回收 0:00:00 然后设置脚本 @echo off @echo 正在关掉所有的IE进程(需要设置默认浏览器是IE) taskkill /im iexpl ...