Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51153
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 142
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-16 21:18
文章分类

全部博文(12)

文章存档

2015年(1)

2014年(1)

2013年(10)

我的朋友

分类: PHP

2013-09-19 02:24:20

    接下来我们探讨的就是它的common.php,它提供了一些函数,这些函数都是功能的罗列,但是不代表它和类一点关系也没有,它往往是在该函数里实例化一个类,然后调用该类的方法.这是一个核心的函数库,它提供的一些功能也是非常的重要,比如类的加载,html标签的转化,读取配置,显示错误,日志处理,http状态的处理等等吧.
    这一节说实话,要想说点东西,恐怕不容易,我们还是仔细分析下它的源码,这里用到的较多的类就是Exception类,即异常类,然后就是Log类,即日志类.好的,多说无益,一切尽在代码里,代码我是通读的,而且做了自我感觉详尽的注释,对我自己和对大家都是很有帮助的把.
    如下几点尤其值得注意:
1.静态数据的应用,可以避免多次初始化,很多数据往往是一次初始化,其他调用的时候只需要返回即可了,所以,静态数据很重要,而诸如配置数据又会经常调用.
2.在函数里调用类的实例,会让oop和aop的使用互补起来.
3.参数为数组和为数组的元素之间的灵活转化,很好用,这一点也希望大家能够经常想到.
4.还有一个是用到了操作系统的判断,这一点对于php这种学习主要在windows下,应用主要在linux下的语言很重要的.

点击(此处)折叠或打开

  1. <?php
  2.     //如果没有定义基路径,则不是从入口文件引用的,为非法引用
  3.     if ( ! defined('BASEPATH')) exit('No direct script access allowed');


  4. //is_php()函数用来判断版本,返回布尔值.
  5. //参数为php的版本.
  6. if ( ! function_exists('is_php'))
  7. {
  8.     function is_php($version = '5.0.0')
  9.     {
  10.         //注意该变量为静态的,就是说只需要判断一次即可.
  11.         //该变量为布尔值.
  12.         static $_is_php;
  13.         //转化为字符串格式.
  14.         $version = (string)$version;

  15.         if ( ! isset($_is_php[$version]))
  16.         {
  17.         //如果版本低于5.0.0,则返回false,否则返回true.
  18.             $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE;
  19.         }

  20.         return $_is_php[$version];
  21.     }
  22. }

  23. //该函数用于判断是否可写,并且需要做到和操作系统无关
  24. if ( ! function_exists('is_really_writable'))
  25. {
  26.     function is_really_writable($file)
  27.     {
  28.         //如果我们在一个Unix服务器并且关了安全模式的话,我们调用is_writeable
  29.         if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE)
  30.         {
  31.             return is_writable($file);
  32.         }

  33.         
  34.         //否则就是windows服务器,
  35.         //对于$file是一个目录的话,则随机生成文件试一试.
  36.         if (is_dir($file))
  37.         {
  38.             $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));
  39.             //如果文件打不开,则返回false.
  40.             if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
  41.             {
  42.                 return FALSE;
  43.             }

  44.             fclose($fp);
  45.             @chmod($file, DIR_WRITE_MODE);
  46.             @unlink($file);
  47.             return TRUE;
  48.         }
  49.         //如果$file不是一个文件或者虽然是文件,但是它文件打开失败.
  50.         elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
  51.         {
  52.             return FALSE;
  53.         }

  54.         fclose($fp);
  55.         return TRUE;
  56.     }
  57. }



  58. //该函数用于加载一个类,返回类型为该类的一个实例.
  59. if ( ! function_exists('load_class'))
  60. {
  61.     function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
  62.     {
  63.         //已经加载的类组成的数组.
  64.         static $_classes = array();

  65.         //如果该类存在,直接返回
  66.         if (isset($_classes[$class]))
  67.         {
  68.             return $_classes[$class];
  69.         }

  70.         $name = FALSE;

  71.         //首先检查用户的类库文件夹,然后检测系统文件夹
  72.         foreach (array(APPPATH, BASEPATH) as $path)
  73.         {
  74.             if (file_exists($path.$directory.'/'.$class.'.php'))
  75.             {
  76.                 $name = $prefix.$class;

  77.                 if (class_exists($name) === FALSE)
  78.                 {
  79.                     require($path.$directory.'/'.$class.'.php');
  80.                 }

  81.                 break;
  82.             }
  83.         }

  84.         //如果这个类是一个扩展类,则我们同样可以加载它.
  85.         if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
  86.         {
  87.             $name = config_item('subclass_prefix').$class;

  88.             if (class_exists($name) === FALSE)
  89.             {
  90.                 require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
  91.             }
  92.         }

  93.         // 我们是否找到了这个类.
  94.         if ($name === FALSE)
  95.         {
  96.             //我们使用exit()而不是show_error(),这样可以避免在异常类里面自身的引用.
  97.             exit('Unable to locate the specified class: '.$class.'.php');
  98.         }

  99.         //保持我们加载过的类的痕迹.
  100.         is_loaded($class);

  101.         $_classes[$class] = new $name();
  102.         return $_classes[$class];
  103.     }
  104. }

  105. //判断类是否被加载
  106. if ( ! function_exists('is_loaded'))
  107. {
  108.     function &is_loaded($class = '')
  109.     {
  110.         static $_is_loaded = array();

  111.         if ($class != '')
  112.         {
  113.             $_is_loaded[strtolower($class)] = $class;
  114.         }

  115.         return $_is_loaded;
  116.     }
  117. }



  118. //读取配置,并且提供了替换配置的功能.
  119. if ( ! function_exists('get_config'))
  120. {
  121.     function &get_config($replace = array())
  122.     {
  123.         static $_config;//定义为静态的,一次初始化即永久引用
  124.         //如果配置项已存在,说明已经完成了,直接返回即可.
  125.         //这里也说明了,如果该函数执行过,那么$replace将起不到作用.
  126.         if (isset($_config))
  127.         {
  128.             return $_config[0];
  129.         }

  130.         // 判断是否指定了应用环境
  131.         if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
  132.         {    
  133.             //注意APPPATH是在入口文件里定义的
  134.             $file_path = APPPATH.'config/config.php';
  135.             
  136.         }
  137.         //判断文件路径是否存在.
  138.         if ( ! file_exists($file_path))
  139.         {
  140.             exit('The configuration file does not exist.');
  141.         }

  142.         require($file_path);

  143.         //注意这里的$config是在$file_path里定义的,此处引用它
  144.         if ( ! isset($config) OR ! is_array($config))
  145.         {
  146.         //说明配置文件存在,但是配置文件里的格式写错了.
  147.             exit('Your config file does not appear to be formatted correctly.');
  148.         }

  149.         //检验是否需要动态的替换.
  150.         if (count($replace) > 0)
  151.         {
  152.             foreach ($replace as $key => $val)
  153.             {
  154.                 if (isset($config[$key]))
  155.                 {
  156.                     $config[$key] = $val;
  157.                 }
  158.             }
  159.         }

  160.         return $_config[0] =& $config;
  161.     }
  162. }

  163. // 返回特定的配置项
  164. if ( ! function_exists('config_item'))
  165. {
  166.     function config_item($item)
  167.     {
  168.         //查看过的配置项,查看一个添加一个,而不是一次就把所有配置项加载进来了.
  169.         static $_config_item = array();

  170.         if ( ! isset($_config_item[$item]))
  171.         {
  172.             $config =& get_config();

  173.             if ( ! isset($config[$item]))
  174.             {
  175.                 return FALSE;
  176.             }
  177.             $_config_item[$item] = $config[$item];
  178.         }

  179.         return $_config_item[$item];
  180.     }
  181. }


  182. //展示错误,需要调用Exceptions这个类.
  183. if ( ! function_exists('show_error'))
  184. {
  185.     function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
  186.     {
  187.         $_error =& load_class('Exceptions', 'core');
  188.         echo $_error->show_error($heading, $message, 'error_general', $status_code);
  189.         exit;
  190.     }
  191. }

  192. //处理404,其实也是在Exception类里面定义好的一个方法.
  193. if ( ! function_exists('show_404'))
  194. {
  195.     function show_404($page = '', $log_error = TRUE)
  196.     {
  197.         $_error =& load_class('Exceptions', 'core');
  198.         $_error->show_404($page, $log_error);
  199.         exit;
  200.     }
  201. }

  202. //日志信息,这里用到了Log类来处理.
  203. if ( ! function_exists('log_message'))
  204. {
  205.     function log_message($level = 'error', $message, $php_error = FALSE)
  206.     {
  207.         //这里的静态保证了该类只需要实例化一次即可.
  208.         static $_log;

  209.         if (config_item('log_threshold') == 0)
  210.         {
  211.             return;
  212.         }

  213.         $_log =& load_class('Log');
  214.         $_log->write_log($level, $message, $php_error);
  215.     }
  216. }

  217. //设置http状态码
  218. if ( ! function_exists('set_status_header'))
  219. {
  220.     function set_status_header($code = 200, $text = '')
  221.     {
  222.         $stati = array(
  223.                             200    => 'OK',
  224.                             201    => 'Created',
  225.                             202    => 'Accepted',
  226.                             203    => 'Non-Authoritative Information',
  227.                             204    => 'No Content',
  228.                             205    => 'Reset Content',
  229.                             206    => 'Partial Content',

  230.                             300    => 'Multiple Choices',
  231.                             301    => 'Moved Permanently',
  232.                             302    => 'Found',
  233.                             304    => 'Not Modified',
  234.                             305    => 'Use Proxy',
  235.                             307    => 'Temporary Redirect',

  236.                             400    => 'Bad Request',
  237.                             401    => 'Unauthorized',
  238.                             403    => 'Forbidden',
  239.                             404    => 'Not Found',
  240.                             405    => 'Method Not Allowed',
  241.                             406    => 'Not Acceptable',
  242.                             407    => 'Proxy Authentication Required',
  243.                             408    => 'Request Timeout',
  244.                             409    => 'Conflict',
  245.                             410    => 'Gone',
  246.                             411    => 'Length Required',
  247.                             412    => 'Precondition Failed',
  248.                             413    => 'Request Entity Too Large',
  249.                             414    => 'Request-URI Too Long',
  250.                             415    => 'Unsupported Media Type',
  251.                             416    => 'Requested Range Not Satisfiable',
  252.                             417    => 'Expectation Failed',

  253.                             500    => 'Internal Server Error',
  254.                             501    => 'Not Implemented',
  255.                             502    => 'Bad Gateway',
  256.                             503    => 'Service Unavailable',
  257.                             504    => 'Gateway Timeout',
  258.                             505    => 'HTTP Version Not Supported'
  259.                         );

  260.         if ($code == '' OR ! is_numeric($code))
  261.         {
  262.             show_error('Status codes must be numeric', 500);
  263.         }

  264.         if (isset($stati[$code]) AND $text == '')
  265.         {
  266.             $text = $stati[$code];
  267.         }

  268.         if ($text == '')
  269.         {
  270.             show_error('No status text available. Please check your status code number or supply your own message text.', 500);
  271.         }

  272.         $server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;

  273.         if (substr(php_sapi_name(), 0, 3) == 'cgi')
  274.         {
  275.             header("Status: {$code} {$text}", TRUE);
  276.         }
  277.         elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0')
  278.         {
  279.             header($server_protocol." {$code} {$text}", TRUE, $code);
  280.         }
  281.         else
  282.         {
  283.             header("HTTP/1.1 {$code} {$text}", TRUE, $code);
  284.         }
  285.     }
  286. }

  287. //异常处理函数.
  288. if ( ! function_exists('_exception_handler'))
  289. {
  290.     function _exception_handler($severity, $message, $filepath, $line)
  291.     {
  292.          //我们不需要修改"strict"模式,因为它们会包含很多多余信息的
  293.          //比如你在php5的环境下运行php4风格的代码(比如不加public等前缀)
  294.          //你会得到一个不被赞成的可以忽视的注意点.
  295.         if ($severity == E_STRICT)
  296.         {
  297.             return;
  298.         }
  299.         //实例化异常类,此处的$_error为Exception的一个实例.
  300.         $_error =& load_class('Exceptions', 'core');

  301.         //我们根据报错级别 来判断是否需要显示该错误.
  302.         if (($severity & error_reporting()) == $severity)
  303.         {
  304.             $_error->show_php_error($severity, $message, $filepath, $line);
  305.         }

  306.         //我们是否需要把它们记录到日志里去??
  307.         if (config_item('log_threshold') == 0)
  308.         {
  309.             return;
  310.         }

  311.         $_error->log_exception($severity, $message, $filepath, $line);
  312.     }
  313. }

  314. //删除不可见字符
  315. if ( ! function_exists('remove_invisible_characters'))
  316. {
  317.     function remove_invisible_characters($str, $url_encoded = TRUE)
  318.     {
  319.         $non_displayables = array();
  320.         
  321.         
  322.         //#10表示换行,#13表示回车,#09表示制表符.
  323.         if ($url_encoded)
  324.         {
  325.             $non_displayables[] = '/%0[0-8bcef]/';    // url encoded 00-08, 11, 12, 14, 15
  326.             $non_displayables[] = '/%1[0-9a-f]/';    // url encoded 16-31
  327.         }
  328.         
  329.         $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';    // 00-08, 11, 12, 14-31, 127

  330.         do
  331.         {
  332.             $str = preg_replace($non_displayables, '', $str, -1, $count);
  333.         }
  334.         while ($count);

  335.         return $str;
  336.     }
  337. }


  338. //html_escape把相应的html标签转化为字符串,可以在一定程度上防注入.
  339. if ( ! function_exists('html_escape'))
  340. {
  341.     function html_escape($var)
  342.     {
  343.         
  344.         if (is_array($var))
  345.         {
  346.             //返回经过html_escape单个处理之后的数组.
  347.             return array_map('html_escape', $var);
  348.         }
  349.         else
  350.         {
  351.             //把html标签转化为字符串.
  352.             return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
  353.         }
  354.     }
  355. }


阅读(1646) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

xinguimeng2013-09-19 02:24:51

文明上网,理性发言...