请选择 进入手机版 | 继续访问电脑版

ylsunyuan技术论坛中心

 找回密码
 注册(请使用中文注册)
搜索
热搜: 活动 交友 discuz
查看: 379|回复: 0

Discuz 代码业务流程分析

[复制链接]

123

主题

126

帖子

614

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
614
发表于 2016-7-1 22:10:16 | 显示全部楼层 |阅读模式
  1. 打开admin.php
  2. define('IN_ADMINCP', TRUE);
  3. //定义常量IN_ADMINCP为true 这样在后面的每个页面都会判断
  4. if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
  5. exit('Access Denied');
  6. }
  7. //防止外面直接访问后台文件,必须通过admin.php包含才可以访问其他文件,IN_DISCUZ在/sorce/class/class_core.php里定义的常量,后面几行马上包含该文件
  8. define('NOROBOT', TRUE);
  9. //定义常量NOROBOT为true,用于阻止搜索引擎爬虫抓取。

  10. define('ADMINSCRIPT', basename(__FILE__));//admin.php
  11. //__FILE__是获取文件磁盘位置详细路径,比如:D:\DedeAMPZ\web2013\discuz_video\upload\admin.php
  12. //basename(__FILE__)就是取文件名 也就是admin.php

  13. define('CURSCRIPT', 'admin');
  14. //定义常量CURSCRIPT为admin,当前脚本为admin
  15. define('HOOKTYPE', 'hookscript');
  16. //定义常量HOOKTYPE 为 hookscript
  17. define('APPTYPEID', 0);
  18. //定义APPTYPEID 为 0
  19. require './source/class/class_core.php';
  20. 包含核心类class_core.php
  21. 程序进入class_core.php内
  22. error_reporting(E_ALL);
  23. //定义错误报告为E_ALL
  24. define('IN_DISCUZ', true);
  25. //定义常量IN_DISCUZ为true 后续判读,防止外界直接访问内部页面
  26. define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));
  27. //定义DISCUZ_ROOT为DISCUZ的根目录也就是upload目录的磁盘位置,这个常量后续会很常用到
  28. define('DISCUZ_CORE_DEBUG', false);
  29. //定义调试模式为 false后续可以修改为true进行调试
  30. define('DISCUZ_TABLE_EXTENDABLE', TRUE);
  31. //定义常量'DISCUZ_TABLE_EXTENDABLE' 为true
  32. set_exception_handler(array('core', 'handleException'));
  33. //PHP自带函数 使用 core::handleException 来执行异常处理可以是单个函数名为参数,也可以是类和函数组成的数组
  34. if(DISCUZ_CORE_DEBUG) {
  35. set_error_handler(array('core', 'handleError'));//设置错误处理函数 core::handleError 来执行
  36. register_shutdown_function(array('core', 'handleShutdown'));//致命错误处理函数 core::handleShutdown 来执行
  37. }
  38. //如果是调试模式的话设置错误处理函数为core::handleError,设置致命错误处理函数为core::handleShutdown
  39. if(function_exists('spl_autoload_register')) {
  40. spl_autoload_register(array('core', 'autoload'));
  41. } else {
  42. function __autoload($class) {
  43.   return core::autoload($class);
  44. }
  45. }
  46. //自动加载类,执行 以下autoload函数 PHP5之后如果试图调用没有加载的类就会自动调用__autoload()函数或者执行spl_autoload_register()指定的函数
  47. //直接调用类时会先调用core::autoload($class)函数,在这个函数里会包含该类文件
  48. C::creatapp();
  49. //执行C::createapp()函数,双冒号是调用类的静态函数。DISCUZ里大多都用的是静态函数
  50. 在类名的最下方有C的定义
  51. class C extends core {}
  52. class DB extends discuz_database {}
  53. 类名C是继承于core的,执行C::createapp()就是执行core::createapp()
  54. 再看core::createapp()函数如下:
  55. public static function creatapp() {
  56.   if(!is_object(self::$_app)) {
  57.    //discuz_application主要定义了mem session misic mobile setting等数组
  58.    //在这里直接调用discuz_application类,会触发core::autoload('discuz_application')执行,因为spl_autoload_register()函数设置了
  59.    self::$_app = discuz_application::instance();//由于执行了spl_autoload_register自动加载类
  60.    //instance执行了$object = new self();这样就执行了__construct函数
  61.   }
  62.   return self::$_app;
  63. }
  64. 该函数直接返回core::$_app , core::$_app 开始为空,所以调用discuz_application::instance();
  65. 由于上面设置了类自动加载,所以调用discuz_application的时候,会先调用
  66. core::autoload()函数,
  67. 函数执行到 core::autoload()里,代码如下:
  68. //自动加载类
  69. public static function autoload($class) {
  70.   $class = strtolower($class);//变为小写
  71.   if(strpos($class, '_') !== false) {
  72.    list($folder) = explode('_', $class);
  73.    $file = 'class/'.$folder.'/'.substr($class, strlen($folder) + 1);
  74.   } else {
  75.    $file = 'class/'.$class;
  76.   }
  77.   try {
  78.    self::import($file);
  79.    return true;
  80.   } catch (Exception $exc) {
  81.    $trace = $exc->getTrace();
  82.    foreach ($trace as $log) {
  83.     if(empty($log['class']) && $log['function'] == 'class_exists') {
  84.      return false;
  85.     }
  86.    }
  87.    discuz_error::exception_error($exc);
  88.   }
  89. }
  90. //此时传递给autoload的变量$class是discuz_application,由于文件名中含有_,所以$file是class/discuz/discuz_application.php,如果没有_的类,则在class/类名.php,然后执行
  91. self::import($file);
  92. 函数进入core::import()内代码如下:
  93. public static function import($name, $folder = '', $force = true) {
  94.   $key = $folder.$name;
  95.   if(!isset(self::$_imports[$key])) {
  96.    $path = DISCUZ_ROOT.'/source/'.$folder;
  97.    if(strpos($name, '/') !== false) {
  98.     $pre = basename(dirname($name));
  99.     $filename = dirname($name).'/'.$pre.'_'.basename($name).'.php';
  100.    } else {
  101.     $filename = $name.'.php';
  102.    }
  103.    if(is_file($path.'/'.$filename)) {
  104.     self::$_imports[$key] = true;
  105.     $rt = include $path.'/'.$filename;
  106.     return $rt;
  107.    } elseif(!$force) {
  108.     return false;
  109.    } else {
  110.     throw new Exception('Oops! System file lost: '.$filename);
  111.    }
  112.   }
  113.   return true;
  114. }
  115. //此时传递给core::import()的参数为class/discuz/discuz_application.php,第2,3个参数为默认的
  116. $key = $folder.$name;
  117.   if(!isset(self::$_imports[$key])) {
  118. 如果包含了文件则不重复包含,包含过后都会把类名保存在$_imports[]数组内,所以开始判断下这个键值是否已经存在,不存在执行下一步,然后下面的代码也就是包含对应的PHP文件了,不详细多说。
  119. 包含了文件后,程序继续执行,因为此时discuz_application已经包含进来,可以继续执行以下函数。
  120. self::$_app = discuz_application::instance();
  121. 执行discuz_application::instance()函数
  122. ----------------------------------------程序即将跳转----------------------------------------
  123. static function &instance() {
  124.   static $object;
  125.   if(empty($object)) {
  126.    $object = new self();//初始化一个类,如此便开始执行__construct()函数
  127.   }
  128.   return $object;
  129. }
  130. 初始化一个类,$object=new self(),初始化后必然执行__construct()函数
  131. ----------------------------------------程序即将跳转----------------------------------------
  132. 代码如下
  133. public function __construct() {
  134.   
  135.   $this->_init_env();//环境设置
  136.   $this->_init_config();//配置
  137.   $this->_init_input();//设置GET,POST ,COOKIE
  138.   $this->_init_output();//rss charset GZIP等。
  139. }
  140. ----------------------------------------程序即将跳转----------------------------------------
  141. $this->_init_env();//环境设置
  142. 代码如下:
  143. private function _init_env() {
  144.   
  145.   error_reporting(E_ERROR);
  146.   if(PHP_VERSION < '5.3.0') {
  147.    set_magic_quotes_runtime(0);
  148.   }
  149.   define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
  150.   define('ICONV_ENABLE', function_exists('iconv'));
  151.   define('MB_ENABLE', function_exists('mb_convert_encoding'));
  152.   define('EXT_OBGZIP', function_exists('ob_gzhandler'));
  153.   define('TIMESTAMP', time());//记录开始时间,没刷新页面都会执行
  154.   $this->timezone_set();//设置时区
  155.   //包含核心函数库
  156.   if(!defined('DISCUZ_CORE_FUNCTION') &&!@include(DISCUZ_ROOT.'./source/function/function_core.php')) {
  157.    exit('function_core.php is missing');
  158.   }
  159.   //内存设置为128M
  160.   if(function_exists('ini_get')) {
  161.    $memorylimit = @ini_get('memory_limit');
  162.    if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists('ini_set')) {
  163.     ini_set('memory_limit', '128m');
  164.    }
  165.   }
  166.   define('IS_ROBOT', checkrobot());
  167.   //$GLOBALS为全局变量数组,比如外部定义了$f00="123",在这里通过$GLOBALS['foo']='123';
  168.   foreach ($GLOBALS as $key => $value) {
  169.    if (!isset($this->superglobal[$key])) {
  170.     $GLOBALS[$key] = null; unset($GLOBALS[$key]);//不明白为何要清空$GLOBALS,似乎是用自己的一套变量清空系统变量
  171.    }
  172.   }
  173.   
  174.   global $_G;//超级大数组
  175.   $_G = array(
  176.    'uid' => 0,
  177.    'username' => '',
  178.    'adminid' => 0,
  179.    'groupid' => 1,
  180.    'sid' => '',
  181.    'formhash' => '',
  182.    'connectguest' => 0,
  183.    'timestamp' => TIMESTAMP,
  184.    'starttime' => microtime(true),
  185.    'clientip' => $this->_get_client_ip(),//获取客户端IP地址
  186.    'referer' => '',
  187.    'charset' => '',
  188.    'gzipcompress' => '',
  189.    'authkey' => '',
  190.    'timenow' => array(),
  191.    'widthauto' => 0,
  192.    'disabledwidthauto' => 0,
  193.    'PHP_SELF' => '',
  194.    'siteurl' => '',
  195.    'siteroot' => '',
  196.    'siteport' => '',
  197.    'pluginrunlist' => !defined('PLUGINRUNLIST') ? array() : explode(',', PLUGINRUNLIST),
  198.    'config' => array(),
  199.    'setting' => array(),
  200.    'member' => array(),
  201.    'group' => array(),
  202.    'cookie' => array(),
  203.    'style' => array(),
  204.    'cache' => array(),
  205.    'session' => array(),
  206.    'lang' => array(),
  207.    'my_app' => array(),
  208.    'my_userapp' => array(),
  209.    'fid' => 0,
  210.    'tid' => 0,
  211.    'forum' => array(),
  212.    'thread' => array(),
  213.    'rssauth' => '',
  214.    'home' => array(),
  215.    'space' => array(),
  216.    'block' => array(),
  217.    'article' => array(),
  218.    'action' => array(
  219.     'action' => APPTYPEID,
  220.     'fid' => 0,
  221.     'tid' => 0,
  222.    ),
  223.    'mobile' => '',
  224.    'notice_structure' => array(
  225.     'mypost' => array('post','pcomment','activity','reward','goods','at'),
  226.     'interactive' => array('poke','friend','wall','comment','click','sharenotice'),
  227.     'system' => array('system','myapp','credit','group','verify','magic','task','show','group','pusearticle','mod_member','blog','article'),
  228.     'manage' => array('mod_member','report','pmreport'),
  229.     'app' => array(),
  230.    ),
  231.    'mobiletpl' => array('1' => 'mobile', '2' => 'touch', '3' => 'wml','yes' => 'mobile'),
  232.   );
  233.   //dhtmlspecialchars 在function_core.php里
  234.   $_G['PHP_SELF'] = dhtmlspecialchars($this->_get_script_url());
  235.   $_G['basescript'] = CURSCRIPT;//在运行首个PHP文件里定义了,比如member.php里定义了member
  236.   $_G['basefilename'] = basename($_G['PHP_SELF']);
  237.   $sitepath = substr($_G['PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'));
  238.   if(defined('IN_API')) {
  239.    $sitepath = preg_replace("/\/api\/?.*?$/i", '', $sitepath);
  240.   } elseif(defined('IN_ARCHIVER')) {
  241.    $sitepath = preg_replace("/\/archiver/i", '', $sitepath);
  242.   }
  243.   
  244.   $_G['isHTTPS'] = ($_SERVER['HTTPS'] && strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
  245.   $_G['siteurl'] = dhtmlspecialchars('http'.($_G['isHTTPS'] ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$sitepath.'/');
  246.   $url = parse_url($_G['siteurl']);
  247.   $_G['siteroot'] = isset($url['path']) ? $url['path'] : '';
  248.   $_G['siteport'] = empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' || $_SERVER['SERVER_PORT'] == '443' ? '' : ':'.$_SERVER['SERVER_PORT'];
  249.   if(defined('SUB_DIR')) {
  250.    $_G['siteurl'] = str_replace(SUB_DIR, '/', $_G['siteurl']);
  251.    $_G['siteroot'] = str_replace(SUB_DIR, '/', $_G['siteroot']);
  252.   }
  253.   
  254.   $this->var = & $_G;
  255. }
  256. ----------------------------------------程序即将跳转----------------------------------------
  257. $this->_init_env();//环境设置
  258. $this->_init_config();//配置
  259.   $this->_init_input();//设置GET,POST ,COOKIE
  260.   $this->_init_output();//rss charset GZIP等。
复制代码

回复

使用道具 举报

本版积分规则

QQ|Archiver|手机版|小黑屋|ylsunyuan技术论坛 ( 桂ICP备14005218号-1

GMT+8, 2018-9-20 00:38 , Processed in 0.069391 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表