PHP容易MVC架构
PHP简单MVC架构由于需要搭建一个简单的框架来进行API接口开发,所以简单的mvc框架当然是首选.最原始,最简洁的mvc框架.下面来介绍下.
一. 项目目录结构:app
|-controller 存放控制器文件
|-model 存放模型文件
|-view 存放视图文件
core
|-lib 存放自定义类库
|-config 存放配置文件
|--config.php 系统配置文件
|--conn.php 数据库连接文件
|--db_config.php
数据库配置文件
|-mysql_db.php 数据库类文件
|-runtime 缓存文件
db_caches 数据库缓存文件
logs日志文件
|-index.php 入口文件
| -dispatcher.php
| -loader.php
| -router.php
二.项目架构1.先介绍index.php,附源码:
,即调用initializer类的一个静态函数initialize,因为我们在ini.php,设置了include_path,以及定义了__autoload,所以程序会自动在core/main目录查找initializer.php. $router = loader::load("router");//加载URL处理文件,对url进行解析--加载loader函数的静态函数load dispatcher::dispatch($router);//router.php文件,这个文件的作用就是映射URL,对URL进行解析.根据解析到的URL参数加载相关controller及action ?>
2.初始化项目文件 ./core/ini.php 源码:
这个文件首先设置了include_path,也就是我们如果要找包含的文件,告诉系统在这个目录下查找。其实我们定义__autoload()方法,这个方法是在PHP5增加的,就是当我们实例化一个函数的时候,如果本文件没有,就会自动去加载文件
3.加载系统配置文件./core/config.php 源码:
4.加载通用的方法的文件./core/global_fun.php 源码:
* 过滤sql语句的关键字 */ function strip_sql($string){ global $search_arr,$replace_arr; return is_array($string) ? array_map('strip_sql', $string) : preg_replace($search_arr, $replace_arr, $string); } function new_htmlspecialchars($string){ return is_array($string) ? array_map('new_htmlspecialchars', $string) : htmlspecialchars($string,ENT_QUOTES); } function new_addslashes($string){ if(!is_array($string)) return addslashes($string); foreach($string as $key => $val) $string[$key] = new_addslashes($val); return $string; } function new_stripslashes($string) { if(!is_array($string)) return stripslashes($string); foreach($string as $key => $val) $string[$key] = new_stripslashes($val); return $string; } function strip_textarea($string){ return nl2br(str_replace(' ', ' ', htmlspecialchars($string, ENT_QUOTES))); } function strip_js($string, $js = 1){ $string = str_replace(array("\n","\r","\""),array('','',"\\\""),$string); return $js==1 ? "document.write(\"".$string."\");\n" : $string; } //邮件格式验证的函数 function check_email($email) { if(!preg_match("/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/",$email)) { return false; } else return true; } //验证手机号码 function check_mobile($mobile) { $pattern = "/^1\d{10}$/"; if (preg_match($pattern,$mobile)) { Return true; } else { Return false; } } //获取GMTime function get_gmtime() { return (time() - date('Z')); } function to_date($utc_time, $format = 'Y-m-d H:i:s') { if (empty ( $utc_time )) { return ''; } $timezone = 8; $time = $utc_time + $timezone * 3600; return date ($format, $time ); } function to_timespan($str, $format = 'Y-m-d H:i:s') { $timezone = 8; $time = intval(strtotime($str)); if($time!=0) $time = $time - $timezone * 3600; return $time; } function get_http() { return (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://'; } function get_domain() { /* 协议 */ $protocol = get_http(); /* 域名或IP地址 */ if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { $host = $_SERVER['HTTP_X_FORWARDED_HOST']; } elseif (isset($_SERVER['HTTP_HOST'])) { $host = $_SERVER['HTTP_HOST']; } else { /* 端口 */ if (isset($_SERVER['SERVER_PORT'])) { $port = ':' . $_SERVER['SERVER_PORT']; if ((':80' == $port && 'http://' == $protocol) || (':443' == $port && 'https://' == $protocol)) { $port = ''; } } else { $port = ''; } if (isset($_SERVER['SERVER_NAME'])) { $host = $_SERVER['SERVER_NAME'] . $port; } elseif (isset($_SERVER['SERVER_ADDR'])) { $host = $_SERVER['SERVER_ADDR'] . $port; } } return $protocol . $host; } function get_host() { /* 域名或IP地址 */ if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { $host = $_SERVER['HTTP_X_FORWARDED_HOST']; } elseif (isset($_SERVER['HTTP_HOST'])) { $host = $_SERVER['HTTP_HOST']; } else { if (isset($_SERVER['SERVER_NAME'])) { $host = $_SERVER['SERVER_NAME']; } elseif (isset($_SERVER['SERVER_ADDR'])) { $host = $_SERVER['SERVER_ADDR']; } } return $host; } /* * 实现AES加密 * $str : 要加密的字符串 * $keys : 加密密钥 * $iv : 加密向量 * $cipher_alg : 加密方式 */ function aes_ecryptdString($str,$keys="1034567890666450",$iv="1034567890123450",$cipher_alg=MCRYPT_RIJNDAEL_128){ // $encrypted_string= base64_encode(bin2hex(mcrypt_encrypt($cipher_alg,$keys, $str, MCRYPT_MODE_CBC,$iv))); $encrypted_string= bin2hex(mcrypt_encrypt($cipher_alg,$keys, $str, MCRYPT_MODE_CBC,$iv)); return $encrypted_string; } /* * 实现AES解密 * $str : 要解密的字符串 * $keys : 加密密钥 * $iv : 加密向量 * $cipher_alg : 加密方式 */ function aes_decryptString($str,$keys="1034567890666450",$iv="1034567890123450",$cipher_alg=MCRYPT_RIJNDAEL_128){ // $str= base64_decode($str); $decrypted_string= mcrypt_decrypt($cipher_alg,$keys,pack("H*",$str),MCRYPT_MODE_CBC,$iv); return $decrypted_string; } /** * 对数组进行转码操作 * @param $array * @param $in_charset * @param $out_charset */ function iconv_array(&$array,$in_charset,$out_charset) { if(UC_CHARSET!='utf-8') { foreach($array as $k=>$v) { if(is_array($array[$k])) { iconv_array($array[$k],$in_charset,$out_charset); } else { $array[$k] = iconv($in_charset,$out_charset,$array[$k]); } } } } /** * utf8字符转Unicode字符 * @param string $char 要转换的单字符 * @return void */ function utf8_to_unicode($char) { switch(strlen($char)) { case 1: return ord($char); case 2: $n = (ord($char[0]) & 0x3f) << 6; $n += ord($char[1]) & 0x3f; return $n; case 3: $n = (ord($char[0]) & 0x1f) << 12; $n += (ord($char[1]) & 0x3f) << 6; $n += ord($char[2]) & 0x3f; return $n; case 4: $n = (ord($char[0]) & 0x0f) << 18; $n += (ord($char[1]) & 0x3f) << 12; $n += (ord($char[2]) & 0x3f) << 6; $n += ord($char[3]) & 0x3f; return $n; } } /** * utf8字符串分隔为unicode字符串 * @param string $str 要转换的字符串 * @param string $depart 分隔,默认为空格为单字 * @return string */ function str_to_unicode_word($str,$depart=' ') { $arr = array(); $str_len = mb_strlen($str,'utf-8'); for($i = 0;$i < $str_len;$i++) { $s = mb_substr($str,$i,1,'utf-8'); if($s != ' ' && $s != ' ') { $arr[] = 'ux'.utf8_to_unicode($s); } } return implode($depart,$arr); } /** * utf8字符串分隔为unicode字符串 * @param string $str 要转换的字符串 * @return string */ function str_to_unicode_string($str) { $string = str_to_unicode_word($str,''); return $string; } //分词 function div_str($str) { require_once APP_ROOT_PATH."core/lib/words.php"; $words = words::segment($str); $words[] = $str; return $words; } /** * @desc im:十进制数转换成三十六机制数 * @param (int)$num 十进制数 * return 返回:三十六进制数 */ function get_code_bynum($num) { $num = intval($num); if ($num <= 0) return false; $codeArr = array("0","1","2","3","4","5","6","7","8","9",'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); $code = ''; do { $key = ($num - 1) % 36; $code = $codeArr[$key] . $code; $num = floor(($num - $key) / 36); } while ($num > 0); return $code; } /** * @desc im:三十六进制数转换成十机制数 * @param (string)$str 三十六进制数 * return 返回:十进制数 */ function get_num_bycode($str){ $array=array("0","1","2","3","4","5","6","7","8","9","A", "B", "C", "D","E", "F", "G", "H", "I", "J", "K", "L","M", "N", "O","P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y","Z"); $len=strlen($str); for($i=0;$i<$len;$i++){ $index=array_search($str[$i],$array); $sum+=($index+1)*pow(36,$len-$i-1); } return $sum; } ?>5.加载公共方法的文件./core/common.php 源码:
getOne("select value from ".DB_PREFIX."conf where name='".$name."'"); } /* * @des:im:验证手机号码 * @param:$phone */ function check_phone($phone) { if(!empty($phone) && !preg_match("/^1\d{10}$/",$phone)) { return false; } else return true; } /** * @desc get_pwd_strength()im:根据密码字符串判断密码结构 * @param (string)$mobile * return 返回:$msg */ function get_pwd_strength($pwd){ if (strlen(iconv('UTF-8','GBK',$pwd))>30 || strlen(iconv('UTF-8','GBK',$pwd))<6) { return '密码是6-30位的字符串,且必须由字母和数字组成.'; } if(preg_match("/^\d+$/",$pwd)) { return '密码不能为全数字';//全数字 } if(preg_match("/^[a-z]+$/i",$pwd)) { return '密码不能为全字母';//全字母 } if(!preg_match("/^[A-Za-z0-9]+$/",$pwd)) { return '密码只能包含字母和数字';//有数字有字母 "; } return null; } /*ajax返回*/ function ajax_return($data) { header("Content-Type:text/html; charset=utf-8"); echo(json_encode($data)); // echo(base64_encode(json_encode($data))); if (APP_LOG) { $GLOBALS['log']->quit($data); } exit; } /** * 字符串加密函数 * @param string $txt * @param string $key * @return string */ function passport_encrypt($txt, $key = 'IMEMBER_2013') { srand((double)microtime() * 1000000); $encrypt_key = md5(rand(0, 32000)); $ctr = 0; $tmp = ''; for($i = 0;$i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]); } return base64_encode(passport_key($tmp, $key)); } /** * 字符串解密函数 * @param string $txt * @param string $key * @return string */ function passport_decrypt($txt, $key = 'IMEMBER_2013') { $txt = passport_key(base64_decode($txt), $key); $tmp = ''; for($i = 0;$i < strlen($txt); $i++) { if (empty($txt[$i+1])) { return false; } $md5 = $txt[$i]; $tmp .= $txt[++$i] ^ $md5; } return $tmp; } function passport_key($txt, $encrypt_key) { $encrypt_key = md5($encrypt_key); $ctr = 0; $tmp = ''; for($i = 0; $i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $txt[$i] ^ $encrypt_key[$ctr++]; } return $tmp; } /** * 传入图片的地址,自动修复图片的相对路径(如 ./public/logo.png)到绝对路径(如http://www.imember.cc/public/logo.png) * @param unknown $img_path */ function imagePathRevise($img_path){ //判断$img_path的路径是否以http://开头 if (preg_match('/^http:\/\//', $img_path)) { return $img_path; }else{ return IMG_PATH.preg_replace('/^\.\//', '', $img_path); } } //utf8 字符串截取 function msubstr($str, $start=0, $length=15, $charset="utf-8", $suffix=true) { if(function_exists("mb_substr")) { $slice = mb_substr($str, $start, $length, $charset); if($suffix&$slice!=$str) return $slice."…"; return $slice; } elseif(function_exists('iconv_substr')) { return iconv_substr($str,$start,$length,$charset); } $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/"; $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/"; $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/"; $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/"; preg_match_all($re[$charset], $str, $match); $slice = join("",array_slice($match[0], $start, $length)); if($suffix&&$slice!=$str) return $slice."…"; return $slice; } } ?>
6.加载./initializer.php,initializer()用于将所有公用的文件目录在此函数里声明
initializer::initialize();
这就话就是调用initializer类的一个静态函数initialize,因为我们在ini.php,设置了include_path,以及定义了__autoload,所以程序会自动在core/main目录查找initializer.php.
定义了一个静态函数,initialize函数,这个函数就是设置include_path,这样,以后如果包含文件,或者__autoload,就会去这些目录下查找。
7.加载./loader.php文件,源码:
"0003",'msg'=>"非法操作","data"=>"Not a valid object '{$object}' to load")); } if (empty(self::$loaded[$object])){ self::$loaded[$object]= new $object(); } return self::$loaded[$object]; } } ?>8.加载控制层文件./router.php,源码:
"0003",'msg'=>"非法操作",'data'=>"Controller is null")); } $this->route = $routeParts['c']; $this->controller=$routeParts['c']; $this->action=isset($routeParts['act'])? $routeParts['act']:"index"; array_shift($routeParts); array_shift($routeParts); $this->params=$routeParts; } public function getAction() { if (empty($this->action)) $this->action="index"; return $this->action; } public function getController() { return $this->controller; } public function getParams() { return $this->params; } } ?>9.加载数据库连接文件./core/conn.php,源码:
"0009",'msg'=>"连接数据库失败" . mysql_error (),'data'=>''))); // } //第二种方法:定义DB类,加载数据库配置,对数据库SQL进行封装 //加载数据库配置 $dbcfg = require APP_ROOT_PATH."core/config/db_config.php"; if(!defined('DB_PREFIX'))//im:数据库表前缀 define('DB_PREFIX', $dbcfg['DB_PREFIX']); if(!file_exists(APP_ROOT_PATH.'core/runtime/db_caches/')) mkdir(APP_ROOT_PATH.'core/runtime/db_caches/',0777); $pconnect = false; $GLOBALS['db'] = new mysql_db($dbcfg['DB_HOST'].":".$dbcfg['DB_PORT'], $dbcfg['DB_USER'],$dbcfg['DB_PWD'],$dbcfg['DB_NAME'],'utf8',$pconnect); mysql_query("SET NAMES UTF8");//相当于character_set_client(),character_set_connection(),character_set_results()客户端 连接器 返回值三者同时设置编码方式 //检查PHP是否连接上MYSQL if(mysqli_connect_errno()){ die (json_encode(array('recode'=>"0009",'msg'=>"连接数据库失败:" . mysql_error (),'data'=>''))); } //end 定义DB ?>
10.加载数据库配置文件./core/db_config.php,源码:
'localhost', 'DB_NAME'=>'ip', 'DB_USER'=>'sara', 'DB_PWD'=>'abc123', 'DB_PORT'=>'3306', 'DB_PREFIX'=>'base_', ); ?>
11.加载数据库类文件./core/mysql_db.php,源码:mysql_db($dbhost, $dbuser, $dbpw, $dbname, $charset, $pconnect, $quiet); } function mysql_db($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'utf8', $pconnect = 0, $quiet = 0) { if (defined('APP_ROOT_PATH') && !$this->root_path) { $this->root_path = APP_ROOT_PATH; } if ($quiet) { $this->connect($dbhost, $dbuser, $dbpw, $dbname, $charset, $pconnect, $quiet); } else { $this->settings = array( 'dbhost' => $dbhost, 'dbuser' => $dbuser, 'dbpw' => $dbpw, 'dbname' => $dbname, 'charset' => $charset, 'pconnect' => $pconnect ); } } function connect($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'utf8', $pconnect = 0, $quiet = 0) { if ($pconnect) { if (!($this->link_id = @mysql_pconnect($dbhost, $dbuser, $dbpw))) { if (!$quiet) { $this->ErrorMsg("Can't pConnect MySQL Server($dbhost)!"); } return false; } } else { if (PHP_VERSION >= '4.2') { $this->link_id = @mysql_connect($dbhost, $dbuser, $dbpw, true); } else { $this->link_id = @mysql_connect($dbhost, $dbuser, $dbpw); mt_srand((double)microtime() * 1000000); // 对 PHP 4.2 以下的版本进行随机数函数的初始化工作 } if (!$this->link_id) { if (!$quiet) { $this->ErrorMsg("Can't Connect MySQL Server($dbhost)!"); } return false; } } $this->dbhash = md5($this->root_path . $dbhost . $dbuser . $dbpw . $dbname); $this->version = mysql_get_server_info($this->link_id); /* 如果mysql 版本是 4.1+ 以上,需要对字符集进行初始化 */ if ($this->version > '4.1') { if ($charset != 'latin1') { mysql_query("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary", $this->link_id); } if ($this->version > '5.0.1') { mysql_query("SET sql_mode=''", $this->link_id); } } $sqlcache_config_file = $this->root_path . $this->cache_data_dir . 'sqlcache_config_file_' . $this->dbhash . '.php'; @include($sqlcache_config_file); $this->starttime = time(); if ($this->max_cache_time && $this->starttime > $this->mysql_config_cache_file_time + $this->max_cache_time) { if ($dbhost != '.') { $result = mysql_query("SHOW VARIABLES LIKE 'basedir'", $this->link_id); $row = mysql_fetch_assoc($result); if (!empty($row['Value']{ 1}) && $row['Value']{ 1} == ':' && !empty($row['Value']{ 2}) && $row['Value']{ 2} == "\\") { $this->platform = 'WINDOWS'; } else { $this->platform = 'OTHER'; } } else { $this->platform = 'WINDOWS'; } if ($this->platform == 'OTHER' && ($dbhost != '.' && strtolower($dbhost) != 'localhost:3306' && $dbhost != '127.0.0.1:3306') || (PHP_VERSION >= '5.1' && date_default_timezone_get() == 'UTC')) { $result = mysql_query("SELECT UNIX_TIMESTAMP() AS timeline, UNIX_TIMESTAMP('" . date('Y-m-d H:i:s', $this->starttime) . "') AS timezone", $this->link_id); $row = mysql_fetch_assoc($result); if ($dbhost != '.' && strtolower($dbhost) != 'localhost:3306' && $dbhost != '127.0.0.1:3306') { $this->timeline = $this->starttime - $row['timeline']; } if (PHP_VERSION >= '5.1' && date_default_timezone_get() == 'UTC') { $this->timezone = $this->starttime - $row['timezone']; } } $content = '<' . "?php\r\n" . '$this->mysql_config_cache_file_time = ' . $this->starttime . ";\r\n" . '$this->timeline = ' . $this->timeline . ";\r\n" . '$this->timezone = ' . $this->timezone . ";\r\n" . '$this->platform = ' . "'" . $this->platform . "';\r\n?" . '>'; @file_put_contents($sqlcache_config_file, $content); } /* 选择数据库 */ if ($dbname) { if (mysql_select_db($dbname, $this->link_id) === false ) { if (!$quiet) { $this->ErrorMsg("Can't select MySQL database($dbname)!"); } return false; } else { return true; } } else { return true; } } function select_database($dbname) { return mysql_select_db($dbname, $this->link_id); } function set_mysql_charset($charset) { /* 如果mysql 版本是 4.1+ 以上,需要对字符集进行初始化 */ if ($this->version > '4.1') { if (in_array(strtolower($charset), array('gbk', 'big5', 'utf-8', 'utf8'))) { $charset = str_replace('-', '', $charset); } if ($charset != 'latin1') { mysql_query("SET character_set_connection=$charset, character_set_results=$charset, character_set_client=binary", $this->link_id); } } } function fetch_array($query, $result_type = MYSQL_ASSOC) { return mysql_fetch_array($query, $result_type); } function query($sql, $type = '') { if ($this->link_id === NULL) { $this->connect($this->settings['dbhost'], $this->settings['dbuser'], $this->settings['dbpw'], $this->settings['dbname'], $
PHP之友评论