使用PHP搭建本身的MVC框架php
1、什麼是MVC MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構模式,把軟件系統分爲三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。 MVC模式的目的是實現一種動態的程序設計,使後續對程序的修改和擴展簡化,而且使程序某一部分的重複利用成爲可能。除此以外,此模式經過對複雜度的簡化,使程序結構更加直觀。軟件系統經過對自身基本部份分離的同時也賦予了各個基本部分應有的功能。專業人員能夠經過自身的專長分組: (控制器Controller)- 負責轉發請求,對請求進行處理。 (視圖View) – 界面設計人員進行圖形界面設計。 (模型Model) – 程序員編寫程序應有的功能(實現算法等等)、數據庫專家進行數據管理和數據庫設計(能夠實現具體的功能)。 模型(Model) 「數據模型」(Model)用於封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。「模型」有對數據直接訪問的權力,例如對數據庫的訪問。「模型」不依賴「視圖」和「控制器」,也就是說,模型不關心它會被如何顯示或是如何被操做。可是模型中數據的變化通常會經過一種刷新機制被公佈。爲了實現這種機制,那些用於監視此模型的視圖必須事先在此模型上註冊,從而,視圖能夠了解在數據模型上發生的改變。 視圖(View) 視圖層可以實現數據有目的的顯示(理論上,這不是必需的)。在視圖中通常沒有程序上的邏輯。爲了實現視圖上的刷新功能,視圖須要訪問它監視的數據模型(Model),所以應該事先在被它監視的數據那裏註冊。 控制器(Controller) 控制器起到不一樣層面間的組織做用,用於控制應用程序的流程。它處理事件並做出響應。「事件」包括用戶的行爲和數據模型上的改變。 2、爲何要本身開發MVC框架 網絡上有大量優秀的MVC框架可供使用,本教程並非爲了開發一個全面的、終極的MVC框架解決方案,而是將它看做是一個很好的從內部學習PHP的機會,在此過程當中,你將學習面向對象編程和設計模式,並學習到開放中的一些注意事項。 更重要的是,你能夠徹底控制你的框架,並將你的想法融入到你開發的框架中。雖然不必定是作好的,可是你能夠按照你的方式去開發功能和模塊。 3、開始開發本身的MVC框架 在開始開發前,讓咱們先來把項目創建好,假設咱們創建的項目爲todo,那麼接下來的第一步就是把目錄結構先設置好。 雖然在這個教程中不會使用到上面的全部的目錄,可是爲了之後程序的可拓展性,在一開始就把程序目錄設置好使很是必要的。下面就具體說說每一個目錄的做用: application – 存放程序代碼 config – 存放程序配置或數據庫配置 db – 用來存放數據庫備分內容 library – 存放框架代碼 public – 存放靜態文件 scripts – 存放命令行工具 tmp – 存放臨時數據 在目錄設置好之後,咱們接下來就要來頂一下一些代碼的規範: MySQL的表名需小寫並採用複數形式,如items,cars 模塊名(Models)需首字母大寫,並採用單數模式,如Item,Car 控制器(Controllers)需首字母大寫,採用複數形式並在名稱中添加「Controller」,如ItemsController, CarsController 視圖(Views)採用複數形式,並在後面添加行爲做爲文件,如:items/view.php, cars/buy.php 上述的一些規則是爲了能在程序鍾更好的進行互相的調用。接下來就開始真正的編碼了。 第一步將全部的的請求都重定向到public目錄下,解決方案是在todo文件下添加一個.htaccesss文件,文件內容爲: <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] </IfModule> 在咱們把全部的請求都重定向到public目錄下之後,咱們就須要將全部的數據請求都再重定向到public下的index.php文件,因而就須要在public文件夾下也新建一個.htaccess文件,文件內容爲: <IfModule mod_rewrite.c> RewriteEngine On #若是文件存在就直接訪問目錄不進行RewriteRule RewriteCond %{REQUEST_FILENAME} !-f #若是目錄存在就直接訪問目錄不進行RewriteRule RewriteCond %{REQUEST_FILENAME} !-d #將全部其餘URL重寫到 index.php/URL RewriteRule ^(.*)$ index.php?url=$1 [PT,L] </IfModule> 這麼作的主要緣由有: 可使程序有一個單一的入口,將全部除靜態程序之外的程序都重定向到index.php上; 能夠用來生成利於SEO的URL,想要更好的配置URL,後期可能會須要URL路由,這裏先不作介紹了。 作完上面的操做,就應該知道咱們須要作什麼了,沒錯!在public目錄下添加index.php文件,文件內容爲: <?php define('DS',DIRECTORY_SEPARATOR); define('ROOT',dirname(dirname(__FILE__))); $url = $_GET['url']; require_once(ROOT.DS.'library'.DS.'bootstrap.php'); 注意上面的PHP代碼中,並無添加PHP結束符號」?>」,這麼作的主要緣由是:對於只包含PHP代碼的文件,結束標誌(「?>」)最好不存在,PHP自身並不須要結束符號,不添加結束符號能夠很大程度上防止末尾被添加額外的注入內容,讓程序更加安全。 在index.php中,咱們對library文件夾下的bootstrap.php發起了請求,那麼bootstrap.php這個啓動文件中到底會包含哪些內容呢? <?php require_once(ROOT.DS.'config'.DS .'config.php'); require_once(ROOT.DS.'library'.DS .'shared.php'); 以上文件均可以直接在index.php文件中引用,咱們這麼作的緣由是爲了在後期管理和拓展中更加的方便,因此把須要在一開始的時候就加載運行的程序統一放到一個單獨的文件中引用。 先來看看config文件下的config .php文件,該文件的主要做用是設置一些程序的配置項及數據庫鏈接等,主要內容爲: <?php # 設置是否爲開發狀態 define('DEVELOPMENT_ENVIRONMENT',true); # 設置數據庫鏈接所需數據 define('DB_HOST','localhost'); define('DB_NAME','todo'); define('DB_USER','root'); define('DB_PASSWORD','root'); 應該說config.php涉及到的內容並很少,不過是一些基礎數據的一些設置,再來看看library下的共用文件shared.php應該怎麼寫。 <?php /* 檢查是否爲開發環境並設置是否記錄錯誤日誌 */ function setReporting(){ if (DEVELOPMENT_ENVIRONMENT == true) { error_reporting(E_ALL); ini_set('display_errors','On'); } else { error_reporting(E_ALL); ini_set('display_errors','Off'); ini_set('log_errors','On'); ini_set('error_log',ROOT.DS. 'tmp' .DS. 'logs' .DS. 'error.log'); } } /* 檢測敏感字符轉義(Magic Quotes)並移除他們 */ function stripSlashDeep($value){ $value = is_array($value) ? array_map('stripSlashDeep',$value) : stripslashes($value); return $value; } function removeMagicQuotes(){ if (get_magic_quotes_gpc()) { $_GET = stripSlashDeep($_GET); $_POST = stripSlashDeep($_POST); $_COOKIE = stripSlashDeep($_COOKIE); } } /* 檢測全局變量設置(register globals)並移除他們 */ function unregisterGlobals(){ if (ini_get('register_globals')) { $array = array('_SESSION','_POST','_GET','_COOKIE','_REQUEST','_SERVER','_ENV','_FILES'); foreach ($array as $value) { foreach ($GLOBALS[$value] as $key => $var) { if ($var === $GLOBALS[$key]) { unset($GLOBALS[$key]); } } } } } /* 主請求方法,主要目的拆分URL請求 */ function callHook() { global $url; $urlArray = array(); $urlArray = explode("/",$url); $controller = $urlArray[0]; array_shift($urlArray); $action = $urlArray[0]; array_shift($urlArray); $queryString = $urlArray; $controllerName = $controller; $controller = ucwords($controller); $model = rtrim($controller, 's'); $controller .= 'Controller'; $dispatch = new $controller($model,$controllerName,$action); if ((int)method_exists($controller, $action)) { call_user_func_array(array($dispatch,$action),$queryString); } else { /* 生成錯誤代碼 */ } } /* 自動加載控制器和模型 */ function __autoload($className) { if (file_exists(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php')) { require_once(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php'); } else if (file_exists(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php')) { require_once(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php'); } else if (file_exists(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php')) { require_once(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php'); } else { /* 生成錯誤代碼 */ } } setReporting(); removeMagicQuotes(); unregisterGlobals(); callHook(); 接下來的操做就是在library中創建程序所須要的基類,包括控制器、模型和視圖的基類。 新建控制器基類爲controller.class.php,控制器的主要功能就是總調度,具體具體內容以下: <?php class Controller { protected $_model; protected $_controller; protected $_action; protected $_template; function __construct($model, $controller,$action) { $this->_controller = $controller; $this->_action = $action; $this->_model = $model; $this->$model =& new $model; $this->_template =& new Template($controller,$action); } function set($name,$value) { $this->_template->set($name,$value); } function __destruct() { $this->_template->render(); } } 新建控制器基類爲model.class.php,考慮到模型須要對數據庫進行處理,因此能夠新建一個數據庫基類sqlquery.class.php,模型去繼承sqlquery.class.php。 新建sqlquery.class.php,代碼以下: <?php class SQLQuery { protected $_dbHandle; protected $_result; /** 鏈接數據庫 **/ function connect($address, $account, $pwd, $name) { $this->_dbHandle = @mysql_connect($address, $account, $pwd); if ($this->_dbHandle != 0) { if (mysql_select_db($name, $this->_dbHandle)) { return 1; }else { return 0; } }else { return 0; } } /** 中斷數據庫鏈接 **/ function disconnect() { if (@mysql_close($this->_dbHandle) != 0) { return 1; } else { return 0; } } /** 查詢全部數據表內容 **/ function selectAll() { $query = 'select * from `'.$this->_table.'`'; return $this->query($query); } /** 查詢數據表指定列內容 **/ function select($id) { $query = 'select * from `'.$this->_table.'` where `id` = \''.mysql_real_escape_string($id).'\''; return $this->query($query, 1); } /** 自定義SQL查詢語句 **/ function query($query, $singleResult = 0) { $this->_result = mysql_query($query, $this->_dbHandle); if (preg_match("/select/i",$query)) { $result = array(); $table = array(); $field = array(); $tempResults = array(); $numOfFields = mysql_num_fields($this->_result); for ($i = 0; $i < $numOfFields; ++$i) { array_push($table,mysql_field_table($this->_result, $i)); array_push($field,mysql_field_name($this->_result, $i)); } while ($row = mysql_fetch_row($this->_result)) { for ($i = 0;$i < $numOfFields; ++$i) { $table[$i] = trim(ucfirst($table[$i]),"s"); $tempResults[$table[$i]][$field[$i]] = $row[$i]; } if ($singleResult == 1) { mysql_free_result($this->_result); return $tempResults; } array_push($result,$tempResults); } mysql_free_result($this->_result); return($result); } } /** 返回結果集行數 **/ function getNumRows() { return mysql_num_rows($this->_result); } /** 釋放結果集內存 **/ function freeResult() { mysql_free_result($this->_result); } /** 返回MySQL操做錯誤信息 **/ function getError() { return mysql_error($this->_dbHandle); } } 新建model.class.php,代碼以下: <?php class Model extends SQLQuery{ protected $_model; function __construct() { $this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME); $this->_model = get_class($this); $this->_table = strtolower($this->_model)."s"; } function __destruct() { } } 新建視圖基類爲template.class.php,具體代碼以下: <?php class Template { protected $variables = array(); protected $_controller; protected $_action; function __construct($controller,$action) { $this->_controller = $controller; $this->_action =$action; } /* 設置變量 */ function set($name,$value) { $this->variables[$name] = $value; } /* 顯示模板 */ function render() { extract($this->variables); if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'header.php')) { include(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'header.php'); } else { include(ROOT.DS. 'application' .DS. 'views' .DS. 'header.php'); } include (ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. $this->_action . '.php'); if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'footer.php')) { include (ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'footer.php'); } else { include (ROOT.DS. 'application' .DS. 'views' .DS. 'footer.php'); } } } 作完了以上這麼多操做,基本上整個MVC框架已經出來了,下面就該製做咱們的站點了。咱們要作的站點其實很簡單,一個ToDo程序。 首先是在咱們的/application/controller/ 目錄下面新建一個站點控制器類爲ItemsController,命名爲itemscontroller.php,內容爲: <?php class ItemsController extends Controller { function view($id = null,$name = null) { $this->set('title',$name.' - My Todo List App'); $this->set('todo',$this->Item->select($id)); } function viewall() { $this->set('title','All Items - My Todo List App'); $this->set('todo',$this->Item->selectAll()); } function add() { $todo = $_POST['todo']; $this->set('title','Success - My Todo List App'); $this->set('todo',$this->Item->query('insert into items (item_name) values (\''.mysql_real_escape_string($todo).'\')')); } function delete($id) { $this->set('title','Success - My Todo List App'); $this->set('todo',$this->Item->query('delete from items where id = \''.mysql_real_escape_string($id).'\'')); } } 接下來就是先建站點的模型,在咱們的/application/model/ 目錄下面先建一個站點模型類爲Item,內容直接繼承Model,代碼以下: <?php class Item extends Model { } 最後一步是設置咱們站點的視圖部分,咱們如今/application/views/目錄下新建一個items的文件夾,再在items文件夾下創建與控制器重Action相同的文件,分別爲view.php,viewall.php,add.php,delete.php,考慮到這麼頁面中可能須要共用頁首和頁尾,因此再新建兩個文件,命名爲header.php,footer.php,每一個文件的代碼以下: view.php文件:查看單條待處理事務 <h2><?php echo $todo['Item']['item_name']?></h2> <a href="../../../items/delete/<?php echo $todo['Item']['id']?>"> <span>Delete this item</span> </a> viewall.php文件:查看全部待處理事務 <form action="../items/add" method="post"> <input type="text" value="I have to..." onclick="this.value=''" name="todo"> <input type="submit" value="add"> </form> <br/><br/> <?php $number = 0?> <?php foreach ($todo as $todoitem):?> <a href="../items/view/<?php echo $todoitem['Item']['id']?>/<?php echo strtolower(str_replace(" ","-",$todoitem['Item']['item_name']))?>"> <span> <?php echo ++$number?> <?php echo $todoitem['Item']['item_name']?> </span> </a><br/> <?php endforeach?> add.php文件:添加待處理事務 <a href="../items/viewall">Todo successfully added. Click here to go back.</a><br/> delete.php文件:刪除事務 <a href="../../items/viewall">Todo successfully deleted. Click here to go back.</a><br/> header.php:頁首文件 <html> <head> <title><?php echo $title?></title> <style> .item {width:400px;} input {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;} a {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;text-decoration:none;} a:hover {background-color:#BCFC3D;} h1 {color:#000000;font-size:41px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;border-bottom:1px dotted #cccccc;} h2 {color:#000000;font-size:34px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;} </style> </head> <body> <h1>My Todo-List App</h1> footer.php:頁尾文件 </body> </html> 固然還有一個必不可少的操做就是在數據中中創建一張表,具體代碼以下: CREATE TABLE IF NOT EXISTS `items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `item_name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ; 至此一個使用MVC開發的網站就開發完成了,你如今能夠經過訪問http://localhost/todo/items/viewall 查看新建的站點。
PHP簡單MVC架構html
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,附源碼: <?php include("./core/ini.php"); include("./core/config/config.php"); include("./core/global.fun.php"); include("./core/common.php"); initializer::initialize();//加載將要用到的目錄文件,即調用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 源碼: <?php set_include_path(get_include_path() . PATH_SEPARATOR . "core/main"); //set_include_path — Sets the include_path configuration option function __autoload($object){ require_once("{$object}.php"); } 這個文件首先設置了include_path,也就是咱們若是要找包含的文件,告訴系統在這個目錄下查找。其實咱們定義__autoload()方法,這個方法是在PHP5增長的,就是當咱們實例化一個函數的時候,若是本文件沒有,就會自動去加載文件 3.加載系統配置文件./core/config.php 源碼: <?php /* * 設置頁面編碼格式 */ header("content-type:text/html;charset=utf-8"); //禁用錯誤報告 error_reporting(0); date_default_timezone_set("PRC"); //定義常量 define("URL_PATH","http://blog.csdn.net/haiqiao_2010");//服務器IP define('IMG_PATH',"http://blog.csdn.net/haiqiao_2010");//服務器圖片目錄 //判斷日誌是否開啓 defined("APP_LOG") or define("APP_LOG",true); if (APP_LOG) { $GLOBALS['log'] = new APIlog(); set_exception_handler(array($GLOBALS['log'],'quit')); set_error_handler(array($GLOBALS['log'],'error_handle')); } define('IS_CGI',substr(PHP_SAPI, 0,3)=='cgi' ? 1 : 0 ); define('IS_WIN',strstr(PHP_OS, 'WIN') ? 1 : 0 ); define('IS_CLI',PHP_SAPI=='cli'? 1 : 0); if(!defined('APP_NAME')) define('APP_NAME', basename(dirname($_SERVER['SCRIPT_FILENAME']))); if(!IS_CLI) { // 當前文件名 if(!defined('_PHP_FILE_')) { if(IS_CGI) { //CGI/FASTCGI模式下 $_temp = explode('.php',$_SERVER["PHP_SELF"]); define('_PHP_FILE_', rtrim(str_replace($_SERVER["HTTP_HOST"],'',$_temp[0].'.php'),'/')); }else { define('_PHP_FILE_', rtrim($_SERVER["SCRIPT_NAME"],'/')); } } if(!defined('__ROOT__')) { // 網站URL根目錄 if( strtoupper(APP_NAME) == strtoupper(basename(dirname(_PHP_FILE_))) ) { $_root = dirname(dirname(_PHP_FILE_)); }else { $_root = dirname(_PHP_FILE_); } define('__ROOT__', (($_root=='/' || $_root=='\\')?'':$_root)); } //支持的URL模式 define('URL_COMMON', 0); //普通模式 define('URL_PATHINFO', 1); //PATHINFO模式 define('URL_REWRITE', 2); //REWRITE模式 define('URL_COMPAT', 3); // 兼容模式 } if(!defined('APP_ROOT')) {//項目根路徑 // 網站URL根目錄 $_root = dirname(_PHP_FILE_); $_root = (($_root=='/' || $_root=='\\')?'':$_root); $_root = str_replace("/system","",$_root); define('APP_ROOT', $_root ); } if(!defined('APP_ROOT_PATH'))//項目絕對路徑 define('APP_ROOT_PATH', str_replace("\\","/",substr(dirname(__FILE__),0,-11))); if(!defined('PAGE_SIZE'))//im:頁面大小 define('PAGE_SIZE',15); ?> 4.加載通用的方法的文件./core/global_fun.php 源碼: <?php //header("content-type:text/html;charset=utf-8"); /* * 過濾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 源碼: <?php function app_conf($name) { return $GLOBALS['db']->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,就會去這些目錄下查找。 <?php class initializer { public static function initialize() { set_include_path(get_include_path().PATH_SEPARATOR . "core/main"); set_include_path(get_include_path().PATH_SEPARATOR . "core/main/cache"); set_include_path(get_include_path().PATH_SEPARATOR . "core/helpers"); set_include_path(get_include_path().PATH_SEPARATOR . "core/libraries"); set_include_path(get_include_path().PATH_SEPARATOR . "core/config"); set_include_path(get_include_path().PATH_SEPARATOR . "app/controllers"); set_include_path(get_include_path().PATH_SEPARATOR."app/models"); set_include_path(get_include_path().PATH_SEPARATOR."app/views"); } } ?> 7.加載./loader.php文件,源碼: <?php class loader { private static $loaded = array(); public static function load($object){ $valid = array( "library", "view", "model", "helper", "router", "config", "hook", "cache", "db"); if (!in_array($object,$valid)){ // throw new Exception("Not a valid object '{$object}' to load"); ajax_return(array('recode'=>"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,源碼: <?php class router { private $route; private $controller; private $action; private $params; public function __construct() { //base64_decode(str)解碼 $routeParts=$_GET; // $routeParts=base64_decode($_GET); if (!isset($routeParts['c'])){ ajax_return(array('recode'=>"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,源碼: <?php /* * 數據庫鏈接 */ //第一種方法:直接寫入數據庫鏈接參數 // $dblink=mysql_connect("127.0.0.1:3306","sara","abc123"); // mysql_select_db("ipolarbear",$dblink); // mysql_query("SET NAMES UTF8"); // if (!$dblink) { // mysql_query("SET NAMES UTF8"); // die (json_encode(array('recode'=>"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,源碼: <?php return array( 'DB_HOST'=>'localhost', 'DB_NAME'=>'ip', 'DB_USER'=>'sara', 'DB_PWD'=>'abc123', 'DB_PORT'=>'3306', 'DB_PREFIX'=>'base_', ); ?> 11.加載數據庫類文件./core/mysql_db.php,源碼: <?php class mysql_db { var $link_id = NULL; var $settings = array(); var $queryCount = 0; var $queryTime = ''; var $queryLog = array(); var $max_cache_time = 60; // 最大的緩存時間,以秒爲單位 var $cache_data_dir = 'core/runtime/db_caches/'; var $root_path = ''; var $error_message = array(); var $platform = ''; var $version = ''; var $dbhash = ''; var $starttime = 0; var $timeline = 0; var $timezone = 0; var $mysql_config_cache_file_time = 0; var $mysql_disable_cache_tables = array(); // 不容許被緩存的表,遇到將不會進行緩存 function __construct($dbhost, $dbuser, $dbpw, $dbname = '', $charset = 'utf8', $pconnect = 0, $quiet = 0) { $this->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'], $this->settings['charset'], $this->settings['pconnect']); $this->settings = array(); } if ($this->queryCount++ <= 99) { $this->queryLog[] = $sql; } if ($this->queryTime == '') { if (PHP_VERSION >= '5.0.0') { $this->queryTime = microtime(true); } else { $this->queryTime = microtime(); } } /* 噹噹前的時間大於類初始化時間的時候,自動執行 ping 這個自動從新鏈接操做 */ if (PHP_VERSION >= '4.3' && time() > $this->starttime + 1) { mysql_ping($this->link_id); } if (!($query = mysql_query($sql, $this->link_id)) && $type != 'SILENT') { $this->error_message[]['message'] = 'MySQL Query Error'; $this->error_message[]['sql'] = $sql; $this->error_message[]['error'] = mysql_error($this->link_id); $this->error_message[]['errno'] = mysql_errno($this->link_id); $this->ErrorMsg(); return false; } if (defined('DEBUG_MODE') && (DEBUG_MODE & 8) == 8) { $logfilename = $this->root_path . DATA_DIR . '/mysql_query_' . $this->dbhash . '_' . date('Y_m_d') . '.log'; $str = $sql . "\n\n"; if (PHP_VERSION >= '5.0') { file_put_contents($logfilename, $str, FILE_APPEND); } else { $fp = @fopen($logfilename, 'ab+'); if ($fp) { fwrite($fp, $str); fclose($fp); } } } //echo $sql."<br/><br/>======================================<br/><br/>"; return $query; } function affected_rows() { return mysql_affected_rows($this->link_id); } function error() { return mysql_error($this->link_id); } function errno() { return mysql_errno($this->link_id); } function result($query, $row) { return @mysql_result($query, $row); } function num_rows($query) { return mysql_num_rows($query); } function num_fields($query) { return mysql_num_fields($query); } function free_result($query) { return mysql_free_result($query); } function insert_id() { return mysql_insert_id($this->link_id); } function fetchRow($query) { return mysql_fetch_assoc($query); } function fetch_fields($query) { return mysql_fetch_field($query); } function version() { return $this->version; } function ping() { if (PHP_VERSION >= '4.3') { return mysql_ping($this->link_id); } else { return false; } } function escape_string($unescaped_string) { if (PHP_VERSION >= '4.3') { return mysql_real_escape_string($unescaped_string); } else { return mysql_escape_string($unescaped_string); } } function close() { return mysql_close($this->link_id); } function ErrorMsg($message = '', $sql = '') { if ($message) { ajax_return(array('recode'=>"0009",'msg'=>"MySQL server error info:".$message,'data'=>'')); } else { ajax_return(array('recode'=>"0010",'msg'=>"MySQL server error report:".$this->error_message,'data'=>'')); } } /* 仿真 Adodb 函數 */ function selectLimit($sql, $num, $start = 0) { if ($start == 0) { $sql .= ' LIMIT ' . $num; } else { $sql .= ' LIMIT ' . $start . ', ' . $num; } return $this->query($sql); } function getOne($sql, $limited = false) { if ($limited == true) { $sql = trim($sql . ' LIMIT 1'); } $res = $this->query($sql); if ($res !== false) { $row = mysql_fetch_row($res); if ($row !== false) { return $row[0]; } else { return ''; } } else { return false; } } function getOneCached($sql, $cached = 'FILEFIRST') { $cachefirst = ($cached == 'FILEFIRST' || ($cached == 'MYSQLFIRST' && $this->platform != 'WINDOWS')) && $this->max_cache_time; if (!$cachefirst) { return $this->getOne($sql, true); } else { $result = $this->getSqlCacheData($sql, $cached); if (empty($result['storecache']) == true) { return $result['data']; } } $arr = $this->getOne($sql, true); if ($arr !== false && $cachefirst) { $this->setSqlCacheData($result, $arr); } return $arr; } function getAll($sql) { $res = $this->query($sql); if ($res !== false) { $arr = array(); while ($row = mysql_fetch_assoc($res)) { $arr[] = $row; } return $arr; } else { return false; } } function getAllCached($sql, $cached = 'FILEFIRST') { $cachefirst = ($cached == 'FILEFIRST' || ($cached == 'MYSQLFIRST' && $this->platform != 'WINDOWS')) && $this->max_cache_time; if (!$cachefirst) { return $this->getAll($sql); } else { $result = $this->getSqlCacheData($sql, $cached); if (empty($result['storecache']) == true) { return $result['data']; } } $arr = $this->getAll($sql); if ($arr !== false && $cachefirst) { $this->setSqlCacheData($result, $arr); } return $arr; } function getRow($sql, $limited = false) { if ($limited == true) { $sql = trim($sql . ' LIMIT 1'); } $res = $this->query($sql); if ($res !== false) { return mysql_fetch_assoc($res); } else { return false; } } function getRowCached($sql, $cached = 'FILEFIRST') { $cachefirst = ($cached == 'FILEFIRST' || ($cached == 'MYSQLFIRST' && $this->platform != 'WINDOWS')) && $this->max_cache_time; if (!$cachefirst) { return $this->getRow($sql, true); } else { $result = $this->getSqlCacheData($sql, $cached); if (empty($result['storecache']) == true) { return $result['data']; } } $arr = $this->getRow($sql, true); if ($arr !== false && $cachefirst) { $this->setSqlCacheData($result, $arr); } return $arr; } function getCol($sql) { $res = $this->query($sql); if ($res !== false) { $arr = array(); while ($row = mysql_fetch_row($res)) { $arr[] = $row[0]; } return $arr; } else { return false; } } function getColCached($sql, $cached = 'FILEFIRST') { $cachefirst = ($cached == 'FILEFIRST' || ($cached == 'MYSQLFIRST' && $this->platform != 'WINDOWS')) && $this->max_cache_time; if (!$cachefirst) { return $this->getCol($sql); } else { $result = $this->getSqlCacheData($sql, $cached); if (empty($result['storecache']) == true) { return $result['data']; } } $arr = $this->getCol($sql); if ($arr !== false && $cachefirst) { $this->setSqlCacheData($result, $arr); } return $arr; } function autoExecute($table, $field_values, $mode = 'INSERT', $where = '', $querymode = '') { $field_names = $this->getCol('DESC ' . $table); $sql = ''; if ($mode == 'INSERT') { $fields = $values = array(); foreach ($field_names AS $value) { if (@array_key_exists($value, $field_values) == true) { $fields[] = $value; $field_values[$value] = stripslashes($field_values[$value]); $values[] = "'" . addslashes($field_values[$value]) . "'"; } } if (!empty($fields)) { $sql = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')'; } } else { $sets = array(); foreach ($field_names AS $value) { if (array_key_exists($value, $field_values) == true) { $field_values[$value] = stripslashes($field_values[$value]); $sets[] = $value . " = '" . addslashes($field_values[$value]) . "'"; } } if (!empty($sets)) { $sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $sets) . ' WHERE ' . $where; } } if ($sql) { return $this->query($sql, $querymode); } else { return false; } } function autoReplace($table, $field_values, $update_values, $where = '', $querymode = '') { $field_descs = $this->getAll('DESC ' . $table); $primary_keys = array(); foreach ($field_descs AS $value) { $field_names[] = $value['Field']; if ($value['Key'] == 'PRI') { $primary_keys[] = $value['Field']; } } $fields = $values = array(); foreach ($field_names AS $value) { if (array_key_exists($value, $field_values) == true) { $fields[] = $value; $values[] = "'" . $field_values[$value] . "'"; } } $sets = array(); foreach ($update_values AS $key => $value) { if (array_key_exists($key, $field_values) == true) { if (is_int($value) || is_float($value)) { $sets[] = $key . ' = ' . $key . ' + ' . $value; } else { $sets[] = $key . " = '" . $value . "'"; } } } $sql = ''; if (empty($primary_keys)) { if (!empty($fields)) { $sql = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')'; } } else { if ($this->version() >= '4.1') { if (!empty($fields)) { $sql = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')'; if (!empty($sets)) { $sql .= 'ON DUPLICATE KEY UPDATE ' . implode(', ', $sets); } } } else { if (empty($where)) { $where = array(); foreach ($primary_keys AS $value) { if (is_numeric($value)) { $where[] = $value . ' = ' . $field_values[$value]; } else { $where[] = $value . " = '" . $field_values[$value] . "'"; } } $where = implode(' AND ', $where); } if ($where && (!empty($sets) || !empty($fields))) { if (intval($this->getOne("SELECT COUNT(*) FROM $table WHERE $where")) > 0) { if (!empty($sets)) { $sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $sets) . ' WHERE ' . $where; } } else { if (!empty($fields)) { $sql = 'REPLACE INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')'; } } } } } if ($sql) { return $this->query($sql, $querymode); } else { return false; } } function setMaxCacheTime($second) { $this->max_cache_time = $second; } function getMaxCacheTime() { return $this->max_cache_time; } function getSqlCacheData($sql, $cached = '') { $sql = trim($sql); $result = array(); $result['filename'] = $this->root_path . $this->cache_data_dir . 'sqlcache_' . abs(crc32($this->dbhash . $sql)) . '_' . md5($this->dbhash . $sql) . '.php'; $result['data'] = $GLOBALS['cache']->get($result['filename']); if($result['data']===false) { $result['storecache'] = true; } else { $result['storecache'] = false; } return $result; } function setSqlCacheData($result, $data) { if ($result['storecache'] === true && $result['filename']) { $GLOBALS['cache']->set($result['filename'],$data,$this->max_cache_time); } } /* 獲取 SQL 語句中最後更新的表的時間,有多個表的狀況下,返回最新的表的時間 */ function table_lastupdate($tables) { if ($this->link_id === NULL) { $this->connect($this->settings['dbhost'], $this->settings['dbuser'], $this->settings['dbpw'], $this->settings['dbname'], $this->settings['charset'], $this->settings['pconnect']); $this->settings = array(); } $lastupdatetime = '0000-00-00 00:00:00'; $tables = str_replace('`', '', $tables); $this->mysql_disable_cache_tables = str_replace('`', '', $this->mysql_disable_cache_tables); foreach ($tables AS $table) { if (in_array($table, $this->mysql_disable_cache_tables) == true) { $lastupdatetime = '2037-12-31 23:59:59'; break; } if (strstr($table, '.') != NULL) { $tmp = explode('.', $table); $sql = 'SHOW TABLE STATUS FROM `' . trim($tmp[0]) . "` LIKE '" . trim($tmp[1]) . "'"; } else { $sql = "SHOW TABLE STATUS LIKE '" . trim($table) . "'"; } $result = mysql_query($sql, $this->link_id); $row = mysql_fetch_assoc($result); if ($row['Update_time'] > $lastupdatetime) { $lastupdatetime = $row['Update_time']; } } $lastupdatetime = strtotime($lastupdatetime) - $this->timezone + $this->timeline; return $lastupdatetime; } function get_table_name($query_item) { $query_item = trim($query_item); $table_names = array(); /* 判斷語句中是否是含有 JOIN */ if (stristr($query_item, ' JOIN ') == '') { /* 解析通常的 SELECT FROM 語句 */ if (preg_match('/^SELECT.*?FROM\s*((?:`?\w+`?\s*\.\s*)?`?\w+`?(?:(?:\s*AS)?\s*`?\w+`?)?(?:\s*,\s*(?:`?\w+`?\s*\.\s*)?`?\w+`?(?:(?:\s*AS)?\s*`?\w+`?)?)*)/is', $query_item, $table_names)) { $table_names = preg_replace('/((?:`?\w+`?\s*\.\s*)?`?\w+`?)[^,]*/', '\1', $table_names[1]); return preg_split('/\s*,\s*/', $table_names); } } else { /* 對含有 JOIN 的語句進行解析 */ if (preg_match('/^SELECT.*?FROM\s*((?:`?\w+`?\s*\.\s*)?`?\w+`?)(?:(?:\s*AS)?\s*`?\w+`?)?.*?JOIN.*$/is', $query_item, $table_names)) { $other_table_names = array(); preg_match_all('/JOIN\s*((?:`?\w+`?\s*\.\s*)?`?\w+`?)\s*/i', $query_item, $other_table_names); return array_merge(array($table_names[1]), $other_table_names[1]); } } return $table_names; } /* 設置不容許進行緩存的表 */ function set_disable_cache_tables($tables) { if (!is_array($tables)) { $tables = explode(',', $tables); } foreach ($tables AS $table) { $this->mysql_disable_cache_tables[] = $table; } array_unique($this->mysql_disable_cache_tables); } } ?> 至此框架搭建完成,下面來寫一個簡單的例子 三.介紹簡單的實例 controller控制層文件./app/controllers/user.php用戶類 <?php /** * @file: user.php 用戶控制層 * @version: 1.0 * @author: Sara * @create: 2012-12-17 10:15:00 * @update: 2012-12-17 10:15:00 * @access: http://blog.csdn.net/haiqiao_2010 * @copyright: 2012 http://blog.csdn.net/haiqiao_2010 All rights reserved. **/ header('Content-Type: text/html; charset=utf-8'); @require_once './core/config/conn.php'; class user { /* * method __construct * paramemter string $a * return 提示信息/調用方法 */ function __construct() { $action=@trim(@$_REQUEST['act']); if(empty($action)){ $action="index"; }else{ if(!in_array($action,array('index','login','register','userUpdatePwd'))){ ajax_return(array('recode'=>"0003",'msg'=>"非法操做",'data'=>$action)); } } } /* * method index 非法調用 * param * return */ public function index() { ajax_return(array('recode'=>"0003",'msg'=>"非法操做",'data'=>@$_REQUEST['act'])); } /* * method login 用戶登錄(支持郵箱+密碼或者帳號+密碼) * param string $user_name,string $user_pwd,string $l_ip,string $city_name,float $l_xpoint,float $l_ypoint * return 返回成功/失敗已經登錄信息 */ public function login() { $data=json_decode(@$_REQUEST['req']); $user_name_or_email = trim(new_htmlspecialchars(new_addslashes(@$data->user_name))); $user_pwd = trim(new_htmlspecialchars(new_addslashes(@$data->user_pwd))); $log['l_ip'] = trim(new_htmlspecialchars(new_addslashes(@$data->l_ip))); $log['city_name'] = trim(new_htmlspecialchars(new_addslashes(@$data->city_name))); $log['l_xpoint'] = trim(new_htmlspecialchars(new_addslashes(@$data->l_xpoint))); $log['l_ypoint'] = trim(new_htmlspecialchars(new_addslashes(@$data->l_ypoint))); $log['l_type'] = intval(@$data->l_type);//用戶登錄類型:默認爲0,網站登錄,1爲手機端IOS登錄,2爲手機端android $log['l_version'] = trim(new_htmlspecialchars(new_addslashes(@$data->l_version))); if(empty($user_name_or_email)|| empty($user_pwd)) { $r=array('recode'=>"0002",'msg'=>"參數錯誤",'data'=>''); } else { $user_data = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user where (user_name='".$user_name_or_email."' or email = '".$user_name_or_email."') and is_delete = 0"); if(!$user_data) { $r=array('recode'=>"1014",'msg'=>"該用戶不存在,請確認操做.",'data'=>''); } else { if($user_data['user_pwd'] != md5($user_pwd.$user_data['code'])&&$user_data['user_pwd']!=$user_pwd) { $r=array('recode'=>"0012",'msg'=>"用戶密碼不對,請確認您的登錄信息.",'data'=>''); } elseif($user_data['is_effect'] != 1) { $r=array('recode'=>"0011",'msg'=>"帳號未被激活,暫時不能進行以下操做.",'data'=>''); } elseif($user_data['is_locking'] != 0) { $r=array('recode'=>"0014",'msg'=>"帳號已經被鎖定,暫時不能進行以下操做.",'data'=>''); if(app_conf("SHOP_TEL")!='') $r['msg'].="如有疑問,請致電聯繫客服: <".app_conf("SHOP_TEL").">"; } else { //im:查看會員分組是否可以升級 $user_current_group = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user_group where id = ".intval($user_data['group_id'])); $user_group = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user_group where score <=".intval($user_data['score'])." order by score desc"); if($user_current_group['score']<$user_group['score']) { $user_data['group_id'] = intval($user_group['id']); $GLOBALS['db']->query("update ".DB_PREFIX."user set group_id = ".$user_data['group_id']." where id = ".$user_data['id']); $pm_title = "您已經成爲".$user_group['name'].""; $pm_content = "恭喜您,您已經成爲".$user_group['name']."。"; if($user_group['discount']<1) { $pm_content.="您將享有".($user_group['discount']*10)."折的購物優惠"; } send_user_msg($pm_title,$pm_content,0,$user_data['id'],get_gmtime(),0,true,true); } //im:查看會員積分是否可以升級 $user_current_level = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user_level where id = ".intval($user_data['level_id'])); $user_level = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user_level where point <=".intval($user_data['point'])." order by point desc"); if($user_current_level['point']<$user_level['point']) { $user_data['level_id'] = intval($user_level['id']); $GLOBALS['db']->query("update ".DB_PREFIX."user set level_id = ".$user_data['level_id']." where id = ".$user_data['id']); $pm_title = "您已經成爲".$user_level['name'].""; $pm_content = "恭喜您,您已經成爲".$user_level['name']."。"; send_user_msg($pm_title,$pm_content,0,$user_data['id'],get_gmtime(),0,true,true); } if($user_current_level['point']>$user_level['point']) { $user_data['level_id'] = intval($user_level['id']); $GLOBALS['db']->query("update ".DB_PREFIX."user set level_id = ".$user_data['level_id']." where id = ".$user_data['id']); $pm_title = "您已經降爲".$user_level['name'].""; $pm_content = "很報歉,您已經降爲".$user_level['name']."。"; send_user_msg($pm_title,$pm_content,0,$user_data['id'],get_gmtime(),0,true,true); } $log['l_time']=get_gmtime(); $log['user_id']=$user_data['id']; //im:更新最後登錄信息 $GLOBALS['db']->query("update ".DB_PREFIX."user set login_ip = '".$log['l_ip']."',login_time= ".$log['l_time'].",group_id=".intval($user_data['group_id'])." where id =".$user_data['id']); //添加登錄日誌 $GLOBALS['db']->autoExecute("im_user_login_log",$log); //檢查是否爲最新系統版本 $log['l_type'] = intval(@$data->l_type);//用戶登錄類型:默認爲0,網站登錄,1爲手機端IOS登錄,2爲手機端android switch ($log['l_type'])//im_m_package:p_type:手機系統版本類型,默認爲0 ios系統;爲1 android系統 { case "1": $package=$GLOBALS['db']->getRow("select p_version,p_url,is_must from im_m_package where is_effect=1 and p_type=0"); break; case "2": $package=$GLOBALS['db']->getRow("select p_version,p_url,is_must from im_m_package where is_effect=1 and p_type=1"); break; default: break; } if (@$package && strnatcmp($log['l_version'],$package['p_version'])<0) { // $varreg="/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/"; $varreg="/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i"; if(!preg_match($varreg,$package['p_url']))//im:判斷是否爲超連接 { $package['p_url']=URL_PATH.str_replace("./","",$package['p_url']); } $r=array('recode'=>"0015",'msg'=>"用戶登錄成功.",'data'=>array('user_id'=>$user_data['id'],'user_name'=>$user_data['user_name'],'true_name'=>$user_data['true_name'],'email'=>is_null($user_data['email'])?"":$user_data['email'],'mobile'=>is_null($user_data['mobile'])?"":$user_data['mobile'],'l_time'=>to_date($log['l_time']),'p_version'=>$package['p_version'],'p_url'=>$package['p_url'],'is_must'=>$package['is_must'])); } else { $r=array('recode'=>"0015",'msg'=>"用戶登錄成功.",'data'=>array('user_id'=>$user_data['id'],'user_name'=>$user_data['user_name'],'true_name'=>$user_data['true_name'],'email'=>is_null($user_data['email'])?"":$user_data['email'],'mobile'=>is_null($user_data['mobile'])?"":$user_data['mobile'],'l_time'=>to_date($log['l_time']),'p_version'=>$log['l_version'],'p_url'=>"",'is_must'=>"")); } } } } ajax_return($r); } /* * method register 用戶註冊 * param int $type,string $user_name,string $user_pwd,string $email ,string mobile * return 返回成功/失敗 */ public function register() { //{"type":0,"user_name":"sara123","user_pwd":"123456","email":"sara123@qq.com","mobile":"13245678900","xpoint":"119.306938","ypoint":"26.069746","city_name":"\u5b81\u590f","ip":"192.168.1","l_type":"1","l_version":"1.0","verify_code":"123456","msg_id":"12"} // $data=json_encode(array( // "type"=>0, // "user_name"=>"sara123", // "user_pwd"=>"123456", // "email"=>"sara123@qq.com", // "mobile"=>"13245678900", // "xpoint"=>"119.306938", // "ypoint"=>"26.069746", // "city_name"=>"寧夏", // "ip"=>"192.168.1", // "l_type"=>"1", // "l_version"=>"1.0", // "verify_code"=>"123456", // "msg_id"=>12 // )); $data=json_decode(@$_REQUEST['req']); $type = intval(@$data->type);//im:註冊方式:默認爲0:郵箱+帳號;1爲:手機號+帳號 $user_data['user_name'] = strtolower(trim(new_htmlspecialchars(new_addslashes(@$data->user_name)))); $user_data["user_pwd"] = trim(new_htmlspecialchars(new_addslashes(@$data->user_pwd))); $user_data["email"] = trim(new_htmlspecialchars(new_addslashes(@$data->email))); $user_data["mobile"] = trim(new_htmlspecialchars(new_addslashes(@$data->mobile))); $user_data["xpoint"] = doubleval(@$data->xpoint); $user_data["ypoint"] = doubleval(@$data->ypoint); $city_name = trim(new_htmlspecialchars(new_addslashes(@$data->city_name))); $user_data["login_ip"] = trim(new_htmlspecialchars(new_addslashes(@$data->ip))); $l_type = intval(@$data->l_type);//用戶登錄類型:默認爲0,網站登錄,1爲手機端IOS登錄,2爲手機端android $l_version = trim(new_htmlspecialchars(new_addslashes(@$data->l_version))); if($user_data['user_name']==''|| !preg_match("/^[a-z\d]{3,20}$/i", $user_data['user_name'])) { ajax_return(array('recode'=>"1001",'msg'=>"用戶名不能爲空,且爲3-20個由字母和數字組成的字符串.".$data->user_name,'data'=>"")); } else { if($GLOBALS['db']->getOne("select count(*) from ".DB_PREFIX."user where user_name = '".trim($user_data['user_name'])."'")>0) { ajax_return(array('recode'=>"1006",'msg'=>"該用戶名已經存在,請從新填寫",'data'=>'')); } else { $msg=get_pwd_strength($user_data['user_pwd']); if(!empty($msg)) { ajax_return(array('recode'=>"1003",'msg'=>$msg,'data'=>'')); } else { if($type==0) { if(!check_email($user_data['email'])) { ajax_return(array('recode'=>"1003",'msg'=>"郵箱格式不正確.",'data'=>'')); } else { if($GLOBALS['db']->getOne("select count(*) from ".DB_PREFIX."user where email = '".trim($user_data['email'])."'")>0) { ajax_return(array('recode'=>"1004",'msg'=>"該郵箱已經被註冊過,請填寫其餘郵箱.",'data'=>'')); } } } else { if(!check_mobile($user_data['mobile'])) { ajax_return(array('recode'=>"1005",'msg'=>"手機號碼格式錯誤,手機號碼爲11位.",'data'=>'')); } else { $verify_code = trim(new_htmlspecialchars(new_addslashes(@$data->verify_code))); $msg_id = intval(@$data->msg_id); if ($msg_id<=0 || empty($verify_code)) { ajax_return(array('recode'=>"0002",'msg'=>"參數錯誤",'data'=>'')); } $verify_result=use_sms_code(0,0,$msg_id,0,$user_data["mobile"],$verify_code); if($verify_result['status']==0) { ajax_return(array('recode'=>$verify_result['recode'],'msg'=>$verify_result['msg'],'data'=>'')); } } } //驗證結束開始插入數據 $user_data['create_time'] = get_gmtime(); $user_data['update_time'] = get_gmtime(); //獲取默認會員組, 即升級積分最小的會員組 $user_data['group_id'] = $GLOBALS['db']->getOne("select id from ".DB_PREFIX."user_group order by score asc limit 1"); //獲取用戶所在城市id $city = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."region_conf where name='".$city_name."'"); if ($city) { switch ($city['region_level']) {//im:1:國 2:省 3:市(縣) 4:區(鎮) case "2": $user_data['province_id']=$city['id']; break; case "3": $user_data['city_id']=$city['id']; $user_data['province_id'] = $city['pid']; break; default: break; } } //帳號是否激活 // $user_data['is_effect'] = empty($user_data['is_effect'])? app_conf("USER_VERIFY"):$user_data['is_effect']; $user_data['is_effect']=1;//手機端註冊,默認帳號爲激活狀態 $user_data['code'] = ''; //默認不使用code, 該值用於其餘系統導入時的初次認證 $user_data['user_pwd'] = md5($user_data['user_pwd'].$user_data['code']); $user_data['register_type'] = 1;//register_type:im:用戶註冊的方式:默認爲0,web端註冊,1爲手機端註冊 if($GLOBALS['db']->autoExecute(DB_PREFIX."user",$user_data,"INSERT")) { $user_id = $GLOBALS['db']->insert_id(); $register_money = app_conf('USER_REGISTER_MONEY'); $register_score = app_conf('USER_REGISTER_SCORE'); $register_point = app_conf('USER_REGISTER_POINT'); if($register_money>0||$register_score>0) { $user_get['score'] = $register_score; $user_get['money'] = $register_money; $user_get['point'] = $register_point; @require_once './app/modules/userModule.php'; modify_account($user_get,intval($user_id),"在".to_date(get_gmtime())."註冊成功"); } //im:添加登錄日誌 $GLOBALS['db']->autoExecute("im_user_login_log",array('user_id'=>$user_id,'l_type'=>1,'l_ip'=>$user_data['login_ip'],'l_time'=>get_gmtime(),"city_name"=>$city_name,"l_xpoint"=>$user_data['xpoint'],"l_ypoint"=>$user_data['ypoint'],"l_type"=>$l_type,"l_version"=>$l_version)); ajax_return(array('recode'=>"1009",'msg'=>"用戶註冊成功",'data'=>array('user_id'=>$user_id,"user_name"=>$user_data['user_name'],"email"=>is_null($user_data['email'])?"":$user_data['email'],"mobile"=>is_null($user_data['mobile'])?"":$user_data['mobile'],"create_time"=>to_date($user_data['create_time'])))); } else { ajax_return(array('recode'=>"1008",'msg'=>"用戶註冊失敗",'data'=>'')); } } } } } /* * method userUpdatePwd 修改密碼接口 * parameter int $user_id * parameter string $old_pwd * parameter string $new_pwd * return 返回成功/失敗 */ function userUpdatePwd() { //{"user_id":0,"old_pwd":"111@qq.com","new_pwd":"13245678900"} // $data=json_encode(array( // "user_id"=>0, // "old_pwd"=>"sara123@qq.com", // "new_pwd"=>"13245678900" // )); $data=json_decode(@$_REQUEST['req']); $user_id = intval(@$data->user_id); $user_pwd = trim(new_htmlspecialchars(new_addslashes(@$data->old_pwd))); $new_pwd = trim(new_htmlspecialchars(new_addslashes(@$data->new_pwd))); if ($user_id<=0) { $r=array('recode'=>"0002",'msg'=>"參數錯誤.",'data'=>''); } else { $msg=get_pwd_strength($new_pwd); if(!empty($msg)) { $r=array('recode'=>"1002",'msg'=>$msg,'data'=>''); ajax_return($r); } else { $user_data = $GLOBALS['db']->getRow("select * from ".DB_PREFIX."user where id='".$user_id."'"); if(!$user_data) { $r=array('recode'=>"1014",'msg'=>"該用戶不存在,請確認操做.",'data'=>''); } else { if($user_data['user_pwd'] != md5($user_pwd.$user_data['code'])&&$user_data['user_pwd']!=$user_pwd) { $r=array('recode'=>"0012",'msg'=>"用戶密碼不對,請確認您的登錄信息.",'data'=>''); } elseif($user_data['is_effect'] != 1) { $r=array('recode'=>"0011",'msg'=>"帳號未被激活,暫時不能進行以下操做.",'data'=>''); } else if ($user_data['is_delete']==1) { $r=array('recode'=>"1012",'msg'=>"該用戶已被刪除,請從新註冊.",'data'=>''); } else { $user_data['user_pwd'] = $new_pwd; $new_pwd = md5($new_pwd.$user_data['code']); if($GLOBALS['db']->query("update ".DB_PREFIX."user set user_pwd = '".$new_pwd."',password_verify='' where id = ".$user_data['id'] )) { $GLOBALS['db']->query("update ".DB_PREFIX."supplier_account set account_password = '".$new_pwd."' where user_id = ".$user_data['id'] ); $r=array('recode'=>"0000",'msg'=>"操做成功.",'data'=>''); } else { $r=array('recode'=>"0001",'msg'=>"操做失敗.",'data'=>''); } } } } } ajax_return($r); } } ?>
讓thinkphp完美支持smarty模板mysql
Published by 荒野無燈 on 2010-03-11 11:02:28 under PHP Tags:PHP,thinkphp,php框架,smarty,框架,模板 16898 views ThinkPHP_modified_hywd20100217.zip (932.0 KB) 一,去掉了系統自帶的think 模板引擎,用功能強大的smarty替代之,基本上能夠說是完美支持smarty模板了。 原有的smarty模板接口只能實現基本的功能,好比判斷模板是否已經緩存就無能爲力,這樣使用無疑大大削減了smarty的功能。 二,去掉了分組功能 三,默認使用php模板 四,支持帶路由的dispatch 五,支持CURD方法、連貫操做、統計查詢等 六,支持語言包、模板主題 7、去掉了大部分擴展機制 8、完美支持smarty模板引擎(ThinkPHP\Vendor\Smarty) 默認加載 : convention.php defines.php functions.php paths.php runtime.php //生成核心和應用緩存用 core.php //include 文件用 alias.php //include 文件用 THinkphp/Lib/Think/Core Log.class.php Think.class.php Db.class.php Model.class.php App.class.php View.class.php Action.class.php Dispatcher.class.php ThinkPHP\Lib\Think\Exception\ThinkException.class.php THinkphp/Lib/Think/Util/ Debug.class.php Session.class.php 可經過以下配置使用smarty模板引擎: 123456789101112131415161718192021 /* 模板引擎設置 */ 'TMPL_ENGINE_TYPE' => 'Smarty', 'TMPL_TEMPLATE_SUFFIX' => '.html', // 默認模板文件後綴 'TMPL_CACHFILE_SUFFIX' => '.php', // 默認模板緩存後綴 'TMPL_PARSE_STRING' => array('__UPLOAD__'=>__ROOT__.'/Content/',), // 模板引擎要自動替換的字符串,必須是數組形式。 'TMPL_ENGINE_CONFIG' => array( 'debugging'=>true, // 'error_reporting'=>'', // 'exception_handler'=>array('ExceptionClass','ExceptionMethod'), 'template_dir' => TMPL_PATH, //模板目錄 'compile_dir' =>TEMP_PATH ,//編譯目錄 'cache_dir' =>CACHE_PATH, //緩存目錄 'caching' => false, //是否啓用緩存 'cache_lifetime' =>60*60*24,//緩存時間s 'left_delimiter'=>'<{', 'right_delimiter' =>'}>', ) , 'TMPL_ENGINE_SMARTY_FILTER'=>array( 'output'=>'trimwhitespace', ), 這裏初定義了smarty的編譯目錄、緩存目錄、是否啓用緩存、緩存時間、以及左定界符和右定界符,還有smarty的filter插件。(此處的trimwithespace用於過濾輸出的html代碼的空白。) 因爲是開發時期,因此我還開啓了smarty 的debugging(注意,因爲修改了左右定界符,因此smarty的debugging模板也要做相應修改)。 關於 thinkphp的視圖類(view) thinkphp的視圖類(view)是在覈心庫文件Action.class.php中__construct的實例化的,此__construct同時執行_initialize方法。 Action.class.php中的display方法是用於調用模板引擎的顯示方法的,此處即爲smarty的顯示方法。爲了讓ThinkPHP支持Smarty的fetch方法和display方法的cache_id,讓thinkphp裏面調用display和fetch就像用smarty時如出一轍,所以必須修改thinkphp Action.class.php中的: protected function display protected function fetch 我還增長了幾個方法(都是smarty裏面的): protected function is_cached protected function clear_cache 具體代碼以下: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 protected function display($templateFile='',$cache_id = null,$compile_id=null,$charset='',$contentType='text/html') { $this->view->display($templateFile,$cache_id,$compile_id,$charset,$contentType); } protected function fetch($templateFile='',$cache_id = null,$compile_id=null,$charset='',$contentType='text/html') { return $this->view->fetch($templateFile,$cache_id ,$compile_id,$charset,$contentType); } //判斷模板文件是否已經被緩存 //若是不是檢查當前模塊的操做模板,參數請用 module:action 方式 protected function is_cached($template, $cache_id = null, $compile_id = null) { if(!file_exists_case($template)) // 自動定位模板文件 $template = $this->view->parseTemplateFile($template); $template=substr($template,strlen(TMPL_PATH)); return $this->view->smarty->is_cached($template, $cache_id, $compile_id); } //清除單一模板文件的緩存 //若是不是清除當前模塊的操做模板,參數請用 module:action 方式 protected function clear_cache($template_name, $cache_id=null, $compile_id=null, $exp_time=null) { if(!file_exists_case($template_name)) // 自動定位模板文件 $template_name = $this->view->parseTemplateFile($template_name); $template_name=substr($template_name,strlen(TMPL_PATH)); return $this->view->smarty->clear_cache($template_name, $cache_id, $compile_id, $exp_time); } //清除全部smarty 靜態緩存 //返回清除的緩存數量 protected function clear_all_cache($exp_time=null) { return $this->view->smarty->clear_all_cache($exp_time); } //清除smarty編譯緩存 //若是不帶參數默認返回清除的編譯緩存數量,帶參數返回 //若是不是清除當前模塊的操做模板,參數請用 module:action 方式 protected function clear_compiled_tpl($template_name=null) { if(null!=$template_name) { if(!file_exists_case($template_name)) // 自動定位模板文件 $template_name = $this->view->parseTemplateFile($template_name); $template_name=substr($template_name,strlen(TMPL_PATH)); } return $this->view->smarty->clear_compiled_tpl($template_name); } 這裏注意,除了is_cached方法,其它的像clear_cache等我額外增長了函數若是在後調用並不會清除前臺的緩存,除非前臺後臺是同一個app 。 進階:讓ThinkPHP支持Smarty的fetch方法的cache_id 這樣之後確定不行,還要修改Lib/Think/Core/View.class.php 增長一個屬性,以支持調用插件: 1234 protected $cache_id=null; //cache_id protected $compile_id=null; //cache_id protected $smarty=null; public $filters=null; 構造函數修改爲以下: 1234567891011121314151617181920212223242526272829303132333435 function __construct() { $this->filters=C('FILTERS'); $engine = strtolower(C('TMPL_ENGINE_TYPE')); if('smarty'==$engine) { vendor('Smarty.Smarty#class'); $tpl = new Smarty(); if(C('TMPL_ENGINE_CONFIG')) { $config = C('TMPL_ENGINE_CONFIG'); foreach ($config as $key=>$val) { $tpl->{$key} = $val; } } else { $tpl->caching = C('TMPL_CACHE_ON'); $tpl->template_dir = TMPL_PATH; $tpl->compile_dir = CACHE_PATH ; $tpl->cache_dir = TEMP_PATH ; } if(C('TMPL_ENGINE_SMARTY_FILTER')) { $filter = C('TMPL_ENGINE_SMARTY_FILTER'); foreach ($filter as $key=>$val) { $tpl->load_filter($key,$val); } } $this->smarty=&$tpl; } } 其中FILTERS是配置文件中定義的,類型爲一維數組。 例如在應用的配置文件中: 1 'FILTERS'=>array('hl_before_highlight_codeblock','hl_replace_attach_tag','hl_after_highlight_codeblock',), 其中的hl_before_highlight_codeblock等函數是在應用的Common/common.php文件中定義的,由於應用在編譯時首先會包含應用目錄下的Common/common.php 。 display方法修改爲以下: 1234 public function display($templateFile='',$cache_id,$compile_id,$charset='',$contentType='text/html') { $this->fetch($templateFile,$cache_id,$compile_id,$charset,$contentType,true); } fetch方法修改爲以下: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 /** +---------------------------------------------------------- * 加載模板和頁面輸出 +---------------------------------------------------------- * @access public +---------------------------------------------------------- * @param string $templateFile 模板文件名 留空爲自動獲取 * @param string $charset 模板輸出字符集 * @param string $contentType 輸出類型 * @param string $display 是否直接顯示 +---------------------------------------------------------- * @return mixed +---------------------------------------------------------- */ public function fetch($templateFile='',$cache_id=null,$compile_id=null,$charset='',$contentType='text/html',$display=false) { $GLOBALS['_viewStartTime'] = microtime(TRUE); if(null===$templateFile) // 使用null參數做爲模版名直接返回不作任何輸出 return ; if(empty($charset)) $charset = C('DEFAULT_CHARSET'); // 網頁字符編碼 header("Content-Type:".$contentType."; charset=".$charset); header("Cache-control: private"); //支持頁面回跳 //頁面緩存 ob_start(); ob_implicit_flush(0); if(!file_exists_case($templateFile)) // 自動定位模板文件 $templateFile = $this->parseTemplateFile($templateFile); $engine = strtolower(C('TMPL_ENGINE_TYPE')); if('php'==$engine) { // 模板陣列變量分解成爲獨立變量 extract($this->tVar, EXTR_OVERWRITE); // 直接載入PHP模板 include $templateFile; } else { // 調用 smarty // 調用模板引擎解析和輸出 $templateFile=substr($templateFile,strlen(TMPL_PATH)); $this->smarty->assign($this->tVar); $this->smarty->display($templateFile,$cache_id,$compile_id); } $this->templateFile = $templateFile; $cache_id && $this->cache_id=$cache_id; //存儲cache_id ,荒野無燈添加 $compile_id && $this->compile_id=$compile_id; //存儲cache_id ,荒野無燈添加 // 獲取並清空緩存 $content = ob_get_clean(); // 模板內容替換 $content = $this->templateContentReplace($content); if(null!=$this->filters && is_array($this->filters)) { $filterArray=$this->filters; for($i=0;$i<count($filterArray);$i++) { $content=call_user_func($filterArray[$i],$content); //array_shift($filterArray); } } // 輸出模板文件 return $this->output($content,$display); } 更多2