文件位于system/core/common.php,是框架核心文件。
该文件中定义了一系列的函数,都是框架运行中经常需要用到的。下面逐一介绍。
is_php
1 /** 2 * Determines if the current version of PHP is equal to or greater than the supplied value 3 * 4 * @param string 5 * @return bool TRUE if the current version is $version or higher 6 */ 7 function is_php($version) 8 { 9 static $_is_php; 10 $version = (string) $version; 11 12 if ( ! isset($_is_php[$version])) 13 { 14 $_is_php[$version] = version_compare(PHP_VERSION, $version, '>='); 15 } 16 17 return $_is_php[$version]; 18 } 19 }
该函数用于进行php版本比较,如果运行的php版本大于等于输入的php版本参数,则返回true。这里建立了一个$is_php静态数组,把新版本参数比较的结果存在数组里,如果再有类似的版本参数传入,不用比较,直接返回结果。是一种空间换时间的做法。
is_really_writable
1 /** 2 * Tests for file writability 3 * 4 * is_writable() returns TRUE on Windows servers when you really can't write to 5 * the file, based on the read-only attribute. is_writable() is also unreliable 6 * on Unix servers if safe_mode is on. 7 * 8 * @link https://bugs.php.net/bug.php?id=54709 9 * @param string 10 * @return bool 11 */ 12 function is_really_writable($file) 13 { 14 // If we're on a Unix server with safe_mode off we call is_writable 15 //用DIRECTORY_SEPARATOR === '/'来判断是unix系统, 16 if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode'))) 17 { 18 return is_writable($file); 19 } 20 21 /* For Windows servers and safe_mode "on" installations we'll actually 22 * write a file then read it. Bah... 23 * 对于windows操作系统和安全模式的处理方法 24 */ 25 if (is_dir($file))//对于目录 26 { 27 $file = rtrim($file, '/').'/'.md5(mt_rand()); 28 if (($fp = @fopen($file, 'ab')) === FALSE) 29 { 30 return FALSE; 31 } 32 33 fclose($fp); 34 @chmod($file, 0777); 35 @unlink($file); 36 return TRUE; 37 } 38 elseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE)//对于文件 39 { 40 return FALSE; 41 } 42 43 fclose($fp); 44 return TRUE; 45 }
该函数用于判断文件或目录是否可写。
对于linux系统未使用安全模式的情况,直接调用php函数is_writable($file)即可。
对于windows系统和使用安全模式的linux系统则根据是文件夹还是文件采取不同的方式:文件夹是 在看是否可在里面新建一个可读写的文件;文件是看是否可读写打开。
&load_class
1 /** 2 * Class registry 3 * 4 * This function acts as a singleton. If the requested class does not 5 * exist it is instantiated and set to a static variable. If it has 6 * previously been instantiated the variable is returned. 7 * 8 * @param string the class name being requested 9 * @param string the directory where the class should be found 10 * @param mixed an optional argument to pass to the class constructor 11 * @return object 12 */ 13 function &load_class($class, $directory = 'libraries', $param = NULL) 14 { 15 static $_classes = array(); 16 17 // Does the class exist? If so, we're done... 18 if (isset($_classes[$class])) 19 { 20 return $_classes[$class]; 21 } 22 23 $name = FALSE; 24 25 // Look for the class first in the local application/libraries folder 26 // then in the native system/libraries folder 27 foreach (array(APPPATH, BASEPATH) as $path) 28 { 29 if (file_exists($path.$directory.'/'.$class.'.php')) 30 { 31 $name = 'CI_'.$class; 32 33 if (class_exists($name, FALSE) === FALSE) 34 { 35 require_once($path.$directory.'/'.$class.'.php'); 36 } 37 38 break; 39 } 40 } 41 42 // Is the request a class extension? If so we load it too 43 if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')) 44 { 45 $name = config_item('subclass_prefix').$class; 46 47 if (class_exists($name, FALSE) === FALSE) 48 { 49 require_once(APPPATH.$directory.'/'.$name.'.php'); 50 } 51 } 52 53 // Did we find the class? 54 if ($name === FALSE) 55 { 56 // Note: We use exit() rather than show_error() in order to avoid a 57 // self-referencing loop with the Exceptions class 58 set_status_header(503); 59 echo 'Unable to locate the specified class: '.$class.'.php'; 60 exit(5); // EXIT_UNK_CLASS 61 } 62 63 // Keep track of what we just loaded 64 is_loaded($class); 65 66 $_classes[$class] = isset($param) 67 ? new $name($param) 68 : new $name(); 69 return $_classes[$class]; 70 } 71 }
该函数用于类的注册,核心函数。
这个函数维护一个单例模式,即如果请求注册的类$class已经被实例化过了,则把保存的实例化对象返回,如果没有实例化过,就实例化该类。这个做法避免新建大量的对象,减少内存消耗,也减少了框架使用对象的维护成本,避免使用的混乱。
在搜索类文件的时候,既会搜索系统的类文件,也会搜索用户自定义的类文件。用户自定义类名需要定义统一的前缀,这个前缀在application/config/config.php文件的subclass_prefix变量中定义。
该函数前面有一个&,表明是引用传递返回值。即返回的对象以后发生变化的时候,在这个函数中定义的$_classes[$class]也会发生变化。参考知乎上的解释。
&is_loaded($class = '')
/** * Keeps track of which libraries have been loaded. This function is * called by the load_class() function above * * @param string * @return array */ function &is_loaded($class = '') { static $_is_loaded = array(); if ($class !== '') { $_is_loaded[strtolower($class)] = $class; } return $_is_loaded; }
该函数可以获取已经在load_class函数中注册的类名数组,也可以往 类名数组中添加一个已经注册的类名。使用引用传递返回值。
&get_config(Array $replace = array())
1 /** 2 * Loads the main config.php file 3 * 4 * This function lets us grab the config file even if the Config class 5 * hasn't been instantiated yet 6 * 7 * @param array 8 * @return array 9 */ 10 function &get_config(Array $replace = array()) 11 { 12 static $config; 13 14 if (empty($config)) 15 { 16 $file_path = APPPATH.'config/config.php'; 17 $found = FALSE; 18 if (file_exists($file_path)) 19 { 20 $found = TRUE; 21 require($file_path); 22 } 23 24 // Is the config file in the environment folder? 25 if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) 26 { 27 require($file_path); 28 } 29 elseif ( ! $found) 30 { 31 set_status_header(503); 32 echo 'The configuration file does not exist.'; 33 exit(3); // EXIT_CONFIG 34 } 35 36 // Does the $config array exist in the file? 37 if ( ! isset($config) OR ! is_array($config)) 38 { 39 set_status_header(503); 40 echo 'Your config file does not appear to be formatted correctly.'; 41 exit(3); // EXIT_CONFIG 42 } 43 } 44 45 // Are any values being dynamically added or replaced? 46 foreach ($replace as $key => $val) 47 { 48 $config[$key] = $val; 49 } 50 51 return $config; 52 } 53 }
View Code
该函数用来加载application/config/config.php中的$config数组变量。当然,如果存在,也加载用户根据环境定义的config.php文件。
config.php文件中定义了一些系统和应用程序的设置,包括使用何种编码,是否采用csrf,自定义的类的类名前缀等等。
同时,使用该函数通过$replace也可以追加一些设置。
该函数使用静态局部变量数组$config来存储。使用引用传递返回值。
config_item($item)
1 /** 2 * Returns the specified config item 3 * 4 * @param string 5 * @return mixed 6 */ 7 function config_item($item) 8 { 9 static $_config; 10 11 if (empty($_config)) 12 { 13 // references cannot be directly assigned to static variables, so we use an array 14 $_config[0] =& get_config(); 15 } 16 17 return isset($_config[0][$item]) ? $_config[0][$item] : NULL; 18 }
该函数用于获取某一个具体的在get_config()中定义的$config数组的值。
&get_mimes()
1 /** 2 * Returns the MIME types array from config/mimes.php 3 * 4 * @return array 5 */ 6 function &get_mimes() 7 { 8 static $_mimes; 9 10 if (empty($_mimes)) 11 { 12 $_mimes = file_exists(APPPATH.'config/mimes.php') 13 ? include(APPPATH.'config/mimes.php') 14 : array(); 15 16 if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) 17 { 18 $_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')); 19 } 20 } 21 22 return $_mimes; 23 }
该函数用于获取在application/config/mimes.php中定义的mime类型数组。主要用于文件上传时候的检测。
is_https()
1 /** 2 * Is HTTPS? 3 * 4 * Determines if the application is accessed via an encrypted 5 * (HTTPS) connection. 6 * 7 * @return bool 8 */ 9 function is_https() 10 { 11 if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') 12 { 13 return TRUE; 14 } 15 elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') 16 { 17 return TRUE; 18 } 19 elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') 20 { 21 return TRUE; 22 } 23 24 return FALSE; 25 }
该函数判断请求是否是http请求。
is_cli()
1 /** 2 * Is CLI? 3 * 4 * Test to see if a request was made from the command line. 5 * 6 * @return bool 7 */ 8 function is_cli() 9 { 10 return (PHP_SAPI === 'cli' OR defined('STDIN')); 11 }
该函数用于判断请求是否是命令行方式。