php mysql mvc_超简洁PHPMVC
/**
* 獲取和設置配置參數(shù) 支持批量定義
* 如果$key是關(guān)聯(lián)型數(shù)組,則會按K-V的形式寫入配置
* 如果$key是數(shù)字索引數(shù)組,則返回對應的配置數(shù)組
* @param string|array $key 配置變量
* @param array|null $value 配置值
* @return array|null
*/
function C($key,$value=null){
static $_config = array();
$args = func_num_args();
if($args == 1){
if(is_string($key)){ //如果傳入的key是字符串
return isset($_config[$key])?$_config[$key]:null;
}
if(is_array($key)){
if(array_keys($key) !== range(0, count($key) - 1)){ //如果傳入的key是關(guān)聯(lián)數(shù)組
$_config = array_merge($_config, $key);
}else{
$ret = array();
foreach ($key as $k) {
$ret[$k] = isset($_config[$k])?$_config[$k]:null;
}
return $ret;
}
}
}else{
if(is_string($key)){
$_config[$key] = $value;
}else{
halt('傳入?yún)?shù)不正確');
}
}
return null;
}
/**
* 調(diào)用Widget
* @param string $name widget名
* @param array $data 傳遞給widget的變量列表,key為變量名,value為變量值
* @return void
*/
function W($name, $data = array()){
$fullName = $name.'Widget';
if(!class_exists($fullName)){
halt('Widget '.$name.'不存在');
}
$widget = new $fullName();
$widget->invoke($data);
}
/**
* 終止程序運行
* @param string $str 終止原因
* @param bool $display 是否顯示調(diào)用棧,默認不顯示
* @return void
*/
function halt($str, $display=false){
Log::fatal($str.' debug_backtrace:'.var_export(debug_backtrace(), true));
header("Content-Type:text/html; charset=utf-8");
if($display){
echo "";
debug_print_backtrace();
echo "";
}
echo $str;
exit;
}
/**
* 獲取數(shù)據(jù)庫實例
* @return DB
*/
function M(){
$dbConf = C(array('DB_HOST','DB_PORT','DB_USER','DB_PWD','DB_NAME','DB_CHARSET'));
return DB::getInstance($dbConf);
}
/**
* 如果文件存在就include進來
* @param string $path 文件路徑
* @return void
*/
function includeIfExist($path){
if(file_exists($path)){
include $path;
}
}
/**
* 總控類
*/
class SinglePHP {
/**
* 控制器
* @var string
*/
private $c;
/**
* Action
* @var string
*/
private $a;
/**
* 單例
* @var SinglePHP
*/
private static $_instance;
/**
* 構(gòu)造函數(shù),初始化配置
* @param array $conf
*/
private function __construct($conf){
C($conf);
}
private function __clone(){}
/**
* 獲取單例
* @param array $conf
* @return SinglePHP
*/
public static function getInstance($conf){
if(!(self::$_instance instanceof self)){
self::$_instance = new self($conf);
}
return self::$_instance;
}
/**
* 運行應用實例
* @access public
* @return void
*/
public function run(){
if(C('USE_SESSION') == true){
session_start();
}
C('APP_FULL_PATH', getcwd().'/'.C('APP_PATH').'/');
includeIfExist( C('APP_FULL_PATH').'/common.php');
$pathMod = C('PATH_MOD');
$pathMod = empty($pathMod)?'NORMAL':$pathMod;
spl_autoload_register(array('SinglePHP', 'autoload'));
if(strcmp(strtoupper($pathMod),'NORMAL') === 0 || !isset($_SERVER['PATH_INFO'])){
$this->c = isset($_GET['c'])?$_GET['c']:'Index';
$this->a = isset($_GET['a'])?$_GET['a']:'Index';
}else{
$pathInfo = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:'';
$pathInfoArr = explode('/',trim($pathInfo,'/'));
if(isset($pathInfoArr[0]) && $pathInfoArr[0] !== ''){
$this->c = $pathInfoArr[0];
}else{
$this->c = 'Index';
}
if(isset($pathInfoArr[1])){
$this->a = $pathInfoArr[1];
}else{
$this->a = 'Index';
}
}
if(!class_exists($this->c.'Controller')){
halt('控制器'.$this->c.'不存在');
}
$controllerClass = $this->c.'Controller';
$controller = new $controllerClass();
if(!method_exists($controller, $this->a.'Action')){
halt('方法'.$this->a.'不存在');
}
call_user_func(array($controller,$this->a.'Action'));
}
/**
* 自動加載函數(shù)
* @param string $class 類名
*/
public static function autoload($class){
if(substr($class,-10)=='Controller'){
includeIfExist(C('APP_FULL_PATH').'/Controller/'.$class.'.class.php');
}elseif(substr($class,-6)=='Widget'){
includeIfExist(C('APP_FULL_PATH').'/Widget/'.$class.'.class.php');
}else{
includeIfExist(C('APP_FULL_PATH').'/Lib/'.$class.'.class.php');
}
}
}
/**
* 控制器類
*/
class Controller {
/**
* 視圖實例
* @var View
*/
private $_view;
/**
* 構(gòu)造函數(shù),初始化視圖實例,調(diào)用hook
*/
public function __construct(){
$this->_view = new View();
$this->_init();
}
/**
* 前置hook
*/
protected function _init(){}
/**
* 渲染模板并輸出
* @param null|string $tpl 模板文件路徑
* 參數(shù)為相對于App/View/文件的相對路徑,不包含后綴名,例如index/index
* 如果參數(shù)為空,則默認使用$controller/$action.php
* 如果參數(shù)不包含"/",則默認使用$controller/$tpl
* @return void
*/
protected function display($tpl=''){
if($tpl === ''){
$trace = debug_backtrace();
$controller = substr($trace[1]['class'], 0, -10);
$action = substr($trace[1]['function'], 0 , -6);
$tpl = $controller . '/' . $action;
}elseif(strpos($tpl, '/') === false){
$trace = debug_backtrace();
$controller = substr($trace[1]['class'], 0, -10);
$tpl = $controller . '/' . $tpl;
}
$this->_view->display($tpl);
}
/**
* 為視圖引擎設置一個模板變量
* @param string $name 要在模板中使用的變量名
* @param mixed $value 模板中該變量名對應的值
* @return void
*/
protected function assign($name,$value){
$this->_view->assign($name,$value);
}
/**
* 將數(shù)據(jù)用json格式輸出至瀏覽器,并停止執(zhí)行代碼
* @param array $data 要輸出的數(shù)據(jù)
*/
protected function ajaxReturn($data){
echo json_encode($data);
exit;
}
/**
* 重定向至指定url
* @param string $url 要跳轉(zhuǎn)的url
* @param void
*/
protected function redirect($url){
header("Location: $url");
exit;
}
}
/**
* 視圖類
*/
class View {
/**
* 視圖文件目錄
* @var string
*/
private $_tplDir;
/**
* 視圖文件路徑
* @var string
*/
private $_viewPath;
/**
* 視圖變量列表
* @var array
*/
private $_data = array();
/**
* 給tplInclude用的變量列表
* @var array
*/
private static $tmpData;
/**
* @param string $tplDir
*/
public function __construct($tplDir=''){
if($tplDir == ''){
$this->_tplDir = './'.C('APP_PATH').'/View/';
}else{
$this->_tplDir = $tplDir;
}
}
/**
* 為視圖引擎設置一個模板變量
* @param string $key 要在模板中使用的變量名
* @param mixed $value 模板中該變量名對應的值
* @return void
*/
public function assign($key, $value) {
$this->_data[$key] = $value;
}
/**
* 渲染模板并輸出
* @param null|string $tplFile 模板文件路徑,相對于App/View/文件的相對路徑,不包含后綴名,例如index/index
* @return void
*/
public function display($tplFile) {
$this->_viewPath = $this->_tplDir . $tplFile . '.php';
unset($tplFile);
extract($this->_data);
include $this->_viewPath;
}
/**
* 用于在模板文件中包含其他模板
* @param string $path 相對于View目錄的路徑
* @param array $data 傳遞給子模板的變量列表,key為變量名,value為變量值
* @return void
*/
public static function tplInclude($path, $data=array()){
self::$tmpData = array(
'path' => C('APP_FULL_PATH') . '/View/' . $path . '.php',
'data' => $data,
);
unset($path);
unset($data);
extract(self::$tmpData['data']);
include self::$tmpData['path'];
}
}
/**
* Widget類
* 使用時需繼承此類,重寫invoke方法,并在invoke方法中調(diào)用display
*/
class Widget {
/**
* 視圖實例
* @var View
*/
protected $_view;
/**
* Widget名
* @var string
*/
protected $_widgetName;
/**
* 構(gòu)造函數(shù),初始化視圖實例
*/
public function __construct(){
$this->_widgetName = get_class($this);
$dir = C('APP_FULL_PATH') . '/Widget/Tpl/';
$this->_view = new View($dir);
}
/**
* 處理邏輯
* @param mixed $data 參數(shù)
*/
public function invoke($data){}
/**
* 渲染模板
* @param string $tpl 模板路徑,如果為空則用類名作為模板名
*/
protected function display($tpl=''){
if($tpl == ''){
$tpl = $this->_widgetName;
}
$this->_view->display($tpl);
}
/**
* 為視圖引擎設置一個模板變量
* @param string $name 要在模板中使用的變量名
* @param mixed $value 模板中該變量名對應的值
* @return void
*/
protected function assign($name,$value){
$this->_view->assign($name,$value);
}
}
/**
* 數(shù)據(jù)庫操作類
* 使用方法:
* DB::getInstance($conf)->query('select * from table');
* 其中$conf是一個關(guān)聯(lián)數(shù)組,需要包含以下key:
* DB_HOST DB_USER DB_PWD DB_NAME
* 可以用DB_PORT和DB_CHARSET來指定端口和編碼,默認3306和utf8
*/
class DB {
/**
* 數(shù)據(jù)庫鏈接
* @var resource
*/
private $_db;
/**
* 保存最后一條sql
* @var string
*/
private $_lastSql;
/**
* 上次sql語句影響的行數(shù)
* @var int
*/
private $_rows;
/**
* 上次sql執(zhí)行的錯誤
* @var string
*/
private $_error;
/**
* 實例數(shù)組
* @var array
*/
private static $_instance = array();
/**
* 構(gòu)造函數(shù)
* @param array $dbConf 配置數(shù)組
*/
private function __construct($dbConf){
if(!isset($dbConf['DB_CHARSET'])){
$dbConf['DB_CHARSET'] = 'utf8';
}
$this->_db = mysql_connect($dbConf['DB_HOST'].':'.$dbConf['DB_PORT'],$dbConf['DB_USER'],$dbConf['DB_PWD']);
if($this->_db === false){
halt(mysql_error());
}
$selectDb = mysql_select_db($dbConf['DB_NAME'],$this->_db);
if($selectDb === false){
halt(mysql_error());
}
mysql_set_charset($dbConf['DB_CHARSET']);
}
private function __clone(){}
/**
* 獲取DB類
* @param array $dbConf 配置數(shù)組
* @return DB
*/
static public function getInstance($dbConf){
if(!isset($dbConf['DB_PORT'])){
$dbConf['DB_PORT'] = '3306';
}
$key = $dbConf['DB_HOST'].':'.$dbConf['DB_PORT'];
if(!isset(self::$_instance[$key]) || !(self::$_instance[$key] instanceof self)){
self::$_instance[$key] = new self($dbConf);
}
return self::$_instance[$key];
}
/**
* 轉(zhuǎn)義字符串
* @param string $str 要轉(zhuǎn)義的字符串
* @return string 轉(zhuǎn)義后的字符串
*/
public function escape($str){
return mysql_real_escape_string($str, $this->_db);
}
/**
* 查詢,用于select語句
* @param string $sql 要查詢的sql
* @return bool|array 查詢成功返回對應數(shù)組,失敗返回false
*/
public function query($sql){
$this->_rows = 0;
$this->_error = '';
$this->_lastSql = $sql;
$this->logSql();
$res = mysql_query($sql,$this->_db);
if($res === false){
$this->_error = mysql_error($this->_db);
$this->logError();
return false;
}else{
$this->_rows = mysql_num_rows($res);
$result = array();
if($this->_rows >0) {
while($row = mysql_fetch_array($res, MYSQL_ASSOC)){
$result[] = $row;
}
mysql_data_seek($res,0);
}
return $result;
}
}
/**
* 查詢,用于insert/update/delete語句
* @param string $sql 要查詢的sql
* @return bool|int 查詢成功返回影響的記錄數(shù)量,失敗返回false
*/
public function execute($sql) {
$this->_rows = 0;
$this->_error = '';
$this->_lastSql = $sql;
$this->logSql();
$result = mysql_query($sql, $this->_db) ;
if ( false === $result) {
$this->_error = mysql_error($this->_db);
$this->logError();
return false;
} else {
$this->_rows = mysql_affected_rows($this->_db);
return $this->_rows;
}
}
/**
* 獲取上一次查詢影響的記錄數(shù)量
* @return int 影響的記錄數(shù)量
*/
public function getRows(){
return $this->_rows;
}
/**
* 獲取上一次insert后生成的自增id
* @return int 自增ID
*/
public function getInsertId() {
return mysql_insert_id($this->_db);
}
/**
* 獲取上一次查詢的sql
* @return string sql
*/
public function getLastSql(){
return $this->_lastSql;
}
/**
* 獲取上一次查詢的錯誤信息
* @return string 錯誤信息
*/
public function getError(){
return $this->_error;
}
/**
* 記錄sql到文件
*/
private function logSql(){
Log::sql($this->_lastSql);
}
/**
* 記錄錯誤日志到文件
*/
private function logError(){
$str = '[SQL ERR]'.$this->_error.' SQL:'.$this->_lastSql;
Log::warn($str);
}
}
/**
* 日志類
* 使用方法:Log::fatal('error msg');
* 保存路徑為 App/Log,按天存放
* fatal和warning會記錄在.log.wf文件中
*/
class Log{
/**
* 打日志,支持SAE環(huán)境
* @param string $msg 日志內(nèi)容
* @param string $level 日志等級
* @param bool $wf 是否為錯誤日志
*/
public static function write($msg, $level='DEBUG', $wf=false){
if(function_exists('sae_debug')){ //如果是SAE,則使用sae_debug函數(shù)打日志
$msg = "[{$level}]".$msg;
sae_set_display_errors(false);
sae_debug(trim($msg));
sae_set_display_errors(true);
}else{
$msg = date('[ Y-m-d H:i:s ]')."[{$level}]".$msg."\r\n";
$logPath = C('APP_FULL_PATH').'/Log/'.date('Ymd').'.log';
if($wf){
$logPath .= '.wf';
}
file_put_contents($logPath, $msg, FILE_APPEND);
}
}
/**
* 打印fatal日志
* @param string $msg 日志信息
*/
public static function fatal($msg){
self::write($msg, 'FATAL', true);
}
/**
* 打印warning日志
* @param string $msg 日志信息
*/
public static function warn($msg){
self::write($msg, 'WARN', true);
}
/**
* 打印notice日志
* @param string $msg 日志信息
*/
public static function notice($msg){
self::write($msg, 'NOTICE');
}
/**
* 打印debug日志
* @param string $msg 日志信息
*/
public static function debug($msg){
self::write($msg, 'DEBUG');
}
/**
* 打印sql日志
* @param string $msg 日志信息
*/
public static function sql($msg){
self::write($msg, 'SQL');
}
}
/**
* ExtException類,記錄額外的異常信息
*/
class ExtException extends Exception{
/**
* @var array
*/
protected $extra;
/**
* @param string $message
* @param array $extra
* @param int $code
* @param null $previous
*/
public function __construct($message = "", $extra = array(), $code = 0, $previous = null){
$this->extra = $extra;
parent::__construct($message, $code, $previous);
}
/**
* 獲取額外的異常信息
* @return array
*/
public function getExtra(){
return $this->extra;
}
}
總結(jié)
以上是生活随笔為你收集整理的php mysql mvc_超简洁PHPMVC的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Softmax 函数及其作用(含推导)
- 下一篇: linux cmake编译源码,linu