system/core/Common.php 文件中可以定义 公共函数,我们可以在这里定义自己的公共函数。在任何情况下你都能够使用这些函数。使用他们不需要载入任何类库或辅助函数。

接下来分析下该文件中自带的一些方法:

 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

 // ------------------------------------------------------------------------

 /**
* Common Functions
*/ /**
* 为什么还要定义这些全局函数呢?比如说,下面有很多函数,
* 如get_config()、config_item()这两个方法不是应该由
* core/Config.php这个组件去做么?那个load_class()不应该由core/Loader.php去做么?
* 把这些函数定义出来貌似 感觉架构变得不那么优雅,有点多余。
* 其实是出于这样一种情况:
* 比如说,如果一切和配置有关的动作都由Config组件来完成,
* 一切加载的动作都由Loader来完成,
* 试想一下,如果我要加载Config组件,那么,必须得通过Loader来加载,
* 所以Loader必须比Config要更早实例化,
* 但是如果Loader实例化的时候需要一些和Loader有关的配置信息才能实例化呢?
* 那就必须通过Config来为它取得配置信息。
* 这里就出现了鸡和鸡蛋的问题。。
* 我之前写自己的框架也纠结过这样的问题,后来参考了YII框架,
* 发现它里面其实都有同样的问题,它里面有个Exception的组件,
* 但是在加载这个Exception组件之前,在加载其它组件的时候,
* 如果出错了,那谁来处理异常和错误信息呢?答案就是先定义一些公共的函数。
* 所以这些公共函数就很好地解决了这个问题,这也是为什么Common.php要很早被引入。
*
*/ // ------------------------------------------------------------------------ /**
* Determines if the current version of PHP is greater then the supplied value
*/
if ( ! function_exists('is_php'))
{
//判断当前php版本是不是$version以上的。调用version_compare()这个函数。
function is_php($version = '5.0.0')
{
static $_is_php;
$version = (string)$version; if ( ! isset($_is_php[$version]))
{
//PHP_VERION能够获得当前php版本。
$_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0)
? FALSE : TRUE;
} return $_is_php[$version];
}
} // ------------------------------------------------------------------------ /**
* Tests for file writability
*/
if ( ! function_exists('is_really_writable'))
{
//该函数和php官方手册上面写的差不多,兼容linux/Unix和windows系统:
//http://www.php.net/manual/en/function.is-writable.php
function is_really_writable($file)
{ //DIRECTORY_SEPARATOR是系统的目录分割符。利用它的值可以知道当前是不是linux系统。
if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE)
{
//如果是linux系统的话,那么可以直接调用此方法来判断文件是否可写。
return is_writable($file);
} //如果是windows系统,则尝试写入一个文件来判断。 if (is_dir($file))
{
//如果是目录,则创建一个随机命名的文件。
$file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100)); //如果文件不能创建,则返回不可写。
if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
{
return FALSE;
} fclose($fp);
//删除刚才的文件。
@chmod($file, DIR_WRITE_MODE);
@unlink($file);
return TRUE;
}
elseif ( ! is_file($file)
OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
{
//如果是一个文件,而通过写入方式打不开,则返回不可写。
return FALSE;
} fclose($fp);
return TRUE;
}
} // ------------------------------------------------------------------------ /**
* Class registry
*/
if ( ! function_exists('load_class'))
{
//加载类。默认是加载libraries里面的,如果要加载核心组件,$directory就为'core'
function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
{ //用一个静态数组,保存已经加载过的类的实例,防止多次实例消耗资源,实现单例化。
static $_classes = array();
// Does the class exist? If so, we're done...
if (isset($_classes[$class]))
{
return $_classes[$class];//如果已经保存在这里,就返回它。
}
$name = FALSE;
//这里,如果应用目录下有和系统目录下相同的类的话,优先引入应用目录,也就是你自己定义的。
foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
$name = $prefix.$class;
if (class_exists($name) === FALSE)
{
require($path.$directory.'/'.$class.'.php');
}
break;
}
}
//这里就用到的前缀扩展,如果在应用目录相应的目录下,有自己写的一些对CI库的扩展,
//那么我们加载的是它,而不是原来的。因为我们写的扩展是继承了CI原来的。
//所以可以看出,即使是CI的核心组件(core/下面的)我们都可以为之进行扩展。
if (file_exists(APPPATH.$directory.'/'
.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
if (class_exists($name) === FALSE)
{
require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
}
}
// Did we find the class?
if ($name === FALSE)
{
//这里用的是exit();来提示错误,而不是用show_error();
//这是因为这个load_class的错误有可能
//在加载Exception组件之前发。
exit('Unable to locate the specified class: '.$class.'.php');
}
// Keep track of what we just loaded
//这个函数只是用来记录已经被加载过的类的类名而已。
is_loaded($class);
$_classes[$class] = new $name();
return $_classes[$class];
}
}
// --------------------------------------------------------------------
/**
* Keeps track of which libraries have been loaded. This function is
* called by the load_class() function above
*/
if ( ! function_exists('is_loaded'))
{
//记录有哪些类是已经被加载的。
function is_loaded($class = '')
{
static $_is_loaded = array();
if ($class != '')
{
$_is_loaded[strtolower($class)] = $class;
}
return $_is_loaded;
}
}
// ------------------------------------------------------------------------
/**
* Loads the main config.php file
*/
if ( ! function_exists('get_config'))
{
//这个是读取配置信息的函数,在Config类被实例化之前,由它暂负责。
//而在Config类被实例化之前,我们需要读取的配置信息,
//其实仅仅是config.php这个主配置文件的。所以这个方法是不能读出
//config/下其它配置文件的信息的。
//这个$replace参数,是提供一个临时替换配置信息的机会,仅一次,因为执行一次后,
//配置信息都会保存在静态变量$_config中,不能改变。
function &get_config($replace = array())
{
static $_config;
if (isset($_config))
{
return $_config[0];
}
// Is the config file in the environment folder?
if ( ! defined('ENVIRONMENT') OR
! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
{
$file_path = APPPATH.'config/config.php';
}
// Fetch the config file
if ( ! file_exists($file_path))
{
exit('The configuration file does not exist.');
}
require($file_path);
// Does the $config array exist in the file?
if ( ! isset($config) OR ! is_array($config))
{
exit('Your config file does not appear to be formatted correctly.');
}
// Are any values being dynamically replaced?
if (count($replace) > 0)
{
foreach ($replace as $key => $val)
{
if (isset($config[$key]))
{
$config[$key] = $val;
}
}
}
return $_config[0] =& $config;
}
}
// ------------------------------------------------------------------------
/**
* Returns the specified config item
*/
if ( ! function_exists('config_item'))
{
//取得配置数组中某个元素。
function config_item($item)
{
static $_config_item = array();
if ( ! isset($_config_item[$item]))
{
$config =& get_config();
if ( ! isset($config[$item]))
{
return FALSE;
}
$_config_item[$item] = $config[$item];
}
return $_config_item[$item];
}
}
// ------------------------------------------------------------------------
/**
* Error Handler
*/
//这里的show_error和下面的show_404以及 _exception_handler这三个错误的处理,
//实质都是由Exception组件完成的。
//详见core/Exception.php.
if ( ! function_exists('show_error'))
{
function show_error($message, $status_code = 500,
$heading = 'An Error Was Encountered')
{
$_error =& load_class('Exceptions', 'core');
echo $_error->show_error($heading, $message, 'error_general', $status_code);
exit;
}
}
// ------------------------------------------------------------------------
/**
* 404 Page Handler
*/
if ( ! function_exists('show_404'))
{
function show_404($page = '', $log_error = TRUE)
{
$_error =& load_class('Exceptions', 'core');
$_error->show_404($page, $log_error);
exit;
}
}
// ------------------------------------------------------------------------
/**
* Error Logging Interface
*/
if ( ! function_exists('log_message'))
{
function log_message($level = 'error', $message, $php_error = FALSE)
{
static $_log;
if (config_item('log_threshold') == 0)
{
return;
}
$_log =& load_class('Log');
$_log->write_log($level, $message, $php_error);
}
}
// ------------------------------------------------------------------------
/**
* Set HTTP Status Header
*/
if ( ! function_exists('set_status_header'))
{
function set_status_header($code = 200, $text = '')
{
//此函数构造一个响应头。$stati为响应码与其响应说明。
$stati = array(
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported'
);
//如果调用此函数本身出错,则发出一个错误。
if ($code == '' OR ! is_numeric($code))
{
show_error('Status codes must be numeric', 500);
}
if (isset($stati[$code]) AND $text == '')
{
$text = $stati[$code];
}
//如果$text为空,一般是因为调用此函数时,给的响应码不正确同时又没有写出响应报文信息。
if ($text == '')
{
show_error('No status text available.
Please check your status code number or supply your own message text.', 500);
}
//取得当前协议。
$server_protocol = (isset($_SERVER['SERVER_PROTOCOL']))
? $_SERVER['SERVER_PROTOCOL'] : FALSE;
//php_sapi_name()方法可以获得PHP与服务器之间的接口类型,
//下面是以cgi类型和以服务器模块形式类型的不同发出响应的方式。
if (substr(php_sapi_name(), 0, 3) == 'cgi')
{
header("Status: {$code} {$text}", TRUE);
}
elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0')
{
header($server_protocol." {$code} {$text}", TRUE, $code);
}
else
{
header("HTTP/1.1 {$code} {$text}", TRUE, $code);
}
}
}
// --------------------------------------------------------------------
/**
* Exception Handler
*/
if ( ! function_exists('_exception_handler'))
{
//在CodeIgniter.php中执行set_error_handler('_exception_handler');后,
//以后一切非致命(非fatal)错误信息都由它处理。
//触发错误的时候,会产生几个参数,错误级别(号),错误信息,错误文件,错误行。
function _exception_handler($severity, $message, $filepath, $line)
{
/**
* 有关错误等级的内容可看:
* http://blog.163.com/wu_guoqing/blog/static/19653701820127269312682/
* E_STRICT对于大多数情况来说都是没多大作用的错误提示,
* 这里CI把它屏蔽掉,如果实在要查看,可以查看日志文件。
*/
if ($severity == E_STRICT)
{
return;
}
//真正起到错误处理的是Exception组件。
$_error =& load_class('Exceptions', 'core');
/*
* 注意下面的符号是&而不是&&,php的错误等级的值都是有规律的,
* 例如1,2,4,8...(1,10,100,1000)等等,实际上,php是通过位运算来实现的,
* 使得错误控制更精准。(类似linux的权限控制,rwx)
* 在设置error_reporting()的时候,可通过E_XX|E_YY|E_ZZ的形式来设置,
* 而判断的时候则通过E_XX&error_repoorting()来判断
* E_XX有没有设置。例如1,10,100,1000相或|,则值为1111,
* 则以后1,10,100,1000中任意一个与1111相&,值都为它本身。
* 而E_ALL可以看到是除E_STRICT之外其它等级的“或(|)运算”。
* 个人理解,之所以E_ALL的值是不同版本有所不同的,是
* 因为有时候会加入新的错误级别,从而导致这个E_ALL的值也不一样。
*/
if (($severity & error_reporting()) == $severity)
{
//如果符合则交给Exception组件的show_php_error();进行处理。
$_error->show_php_error($severity, $message, $filepath, $line);
}
//下面两行只是根据配置文件判断要不要log错误信息而已。
if (config_item('log_threshold') == 0)
{
return;
}
$_error->log_exception($severity, $message, $filepath, $line);
}
}
// --------------------------------------------------------------------
/**
* Remove Invisible Characters
*/
if ( ! function_exists('remove_invisible_characters'))
{
function remove_invisible_characters($str, $url_encoded = TRUE)
{
$non_displayables = array();
// every control character except newline (dec 10)
// carriage return (dec 13), and horizontal tab (dec 09)
if ($url_encoded)
{
$non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15
$non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31
}
$non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';
// 00-08, 11, 12, 14-31, 127
do
{
$str = preg_replace($non_displayables, '', $str, -1, $count);
}
while ($count);
return $str;
}
}
// ------------------------------------------------------------------------
/**
* Returns HTML escaped variable
*/
if ( ! function_exists('html_escape'))
{
function html_escape($var)
{
if (is_array($var))
{
return array_map('html_escape', $var);
}
else
{
return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
}
}
}

CI框架 -- 核心文件 之 Common.php的更多相关文章

  1. CI框架 -- 核心文件 之 Hooks.php

    钩子 - 扩展框架核心 CodeIgniter 的钩子特性提供了一种方法来修改框架的内部运作流程,而无需修改 核心文件.CodeIgniter 的运行遵循着一个特定的流程,你可以参考这个页面的 应用程 ...

  2. CI框架 -- 核心文件 之 Exceptions.php

    使用CI框架,我们通常使用一下三个函数处理错误: show_error('消息' [, int $status_code = 500 ] ) show_404('页面' [, 'log_error'] ...

  3. CI框架 -- 核心文件 之 Loader.php(加载器)

    顾名思义,装载器就是加载元素的,使用CI时,经常加载的有: 加载类库文件:$this->load->library()   加载视图文件:$this->load->view() ...

  4. CI框架 -- 核心文件 之 config.php

    Config:该文件包含CI_Config类,这个类包含启用配置文件来管理的方法 /** * 加载配置文件 * * @param string $file 配置文件名 * @param bool $u ...

  5. CI框架 -- 核心文件 之 Output.php(输出类文件)

    CI输出类Output.php的功能是将最终web页面发送给浏览器,这里面的东西可能是你用的最少的.你使用装载器加载了一个视图文件, 这个视图文件的内容会自动传递给输出类对象, 然后呢,在方法执行完毕 ...

  6. CI框架 -- 核心文件 之 Benchmark.php

    Benchmark.php文件中定义的CI_Benchmark类可以让你标记点,并计算它们之间的时间差.还可以显示内存消耗. Benchmarking类库,它是被系统自动被加载的,不需要手工加载 cl ...

  7. CI框架 -- 核心文件 之 Model.php

    class CI_Model { /** * Class constructor * * @return void */ public function __construct() { log_mes ...

  8. CI框架 -- 核心文件 之 Input.php(输入数据处理文件)

    class CI_Input { //用户ip地址 protected $ip_address = FALSE; //用户浏览器地址 protected $user_agent = FALSE; // ...

  9. CI框架 -- 核心文件 之 Lang.php(加载语言包)

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class CI_Lang { var $l ...

随机推荐

  1. 每日英语:A Chinese Father’s Most Important Job

    When it comes to parenting, Chinese fathers say the most important role they play is that of the fam ...

  2. 李洪强iOS经典面试题

    李洪强iOS经典面试题 1. struct和class的区别 swift中,class是引用类型,struct是值类型.值类型在传递和赋值时将进行复制,而引用类型则只会使用引用对象的一个"指 ...

  3. TensorFlow学习笔记(8)--网络模型的保存和读取【转】

    转自:http://blog.csdn.net/lwplwf/article/details/62419087 之前的笔记里实现了softmax回归分类.简单的含有一个隐层的神经网络.卷积神经网络等等 ...

  4. 【Socket】linux套接字技术之tcp

      1.mystery引入      1)UDP也可以编写出C/S程序 ,另外TCP也可以编写点对点通信.    2)网络的本质就是资源共享,当前流行的P2P应用正好暗合了这种精神.    3)当前流 ...

  5. H3C部分笔记

    进入交换机各个视图的命令如下图: 用户视图 系统视图 查看历史命令 配置历史命令缓存大小为30 配置Heade信息 Header 3种类型: incoming:登录终端用户界面时的提示信息. logi ...

  6. 使用一层神经网络训练mnist数据集

    import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...

  7. 线程安全的无锁RingBuffer的实现【一个读线程,一个写线程】

    在程序设计中,我们有时会遇到这样的情况,一个线程将数据写到一个buffer中,另外一个线程从中读数据.所以这里就有多线程竞争的问题.通常的解决办法是对竞争资源加锁.但是,一般加锁的损耗较高.其实,对于 ...

  8. python 基础总结1

    1.python简介特点:    是简单义学,有功能强大,高性能.面向对象,对动态输入的支持.解释性语言的本质,是大多数平台上理想的脚本语言. 简单,义学                    免费, ...

  9. angularjs去掉加载时的{{}}

    添加css <style>        .ng-cloak {display: none;}    </style> 在body头文件中加上class=ng-cloak &l ...

  10. kafka 怎么保证的exactly once

    Kafka auto.offset.reset值详解 发表于2017/7/6 11:25:22  1010人阅读 分类: Kafka 昨天在写一个java消费kafka数据的实例,明明设置auto.o ...