超简洁PHPMVC

php中文网
发布: 2016-07-25 08:47:44
原创
1866人浏览过
原生PHP语法来渲染页面,同时提供了widget功能
  1. /**
  2. * 获取和设置配置参数 支持批量定义
  3. * 如果$key是关联型数组,则会按K-V的形式写入配置
  4. * 如果$key是数字索引数组,则返回对应的配置数组
  5. * @param string|array $key 配置变量
  6. * @param array|null $value 配置值
  7. * @return array|null
  8. */
  9. function C($key,$value=null){
  10. static $_config = array();
  11. $args = func_num_args();
  12. if($args == 1){
  13. if(is_string($key)){ //如果传入的key是字符串
  14. return isset($_config[$key])?$_config[$key]:null;
  15. }
  16. if(is_array($key)){
  17. if(array_keys($key) !== range(0, count($key) - 1)){ //如果传入的key是关联数组
  18. $_config = array_merge($_config, $key);
  19. }else{
  20. $ret = array();
  21. foreach ($key as $k) {
  22. $ret[$k] = isset($_config[$k])?$_config[$k]:null;
  23. }
  24. return $ret;
  25. }
  26. }
  27. }else{
  28. if(is_string($key)){
  29. $_config[$key] = $value;
  30. }else{
  31. halt('传入参数不正确');
  32. }
  33. }
  34. return null;
  35. }
  36. /**
  37. * 调用Widget
  38. * @param string $name widget名
  39. * @param array $data 传递给widget的变量列表,key为变量名,value为变量值
  40. * @return void
  41. */
  42. function W($name, $data = array()){
  43. $fullName = $name.'Widget';
  44. if(!class_exists($fullName)){
  45. halt('Widget '.$name.'不存在');
  46. }
  47. $widget = new $fullName();
  48. $widget->invoke($data);
  49. }
  50. /**
  51. * 终止程序运行
  52. * @param string $str 终止原因
  53. * @param bool $display 是否显示调用栈,默认不显示
  54. * @return void
  55. */
  56. function halt($str, $display=false){
  57. Log::fatal($str.' debug_backtrace:'.var_export(debug_backtrace(), true));
  58. header("Content-Type:text/html; charset=utf-8");
  59. if($display){
  60. echo "
    ";<li>debug_print_backtrace();<li>echo "
    登录后复制
    ";
  61. }
  62. echo $str;
  63. exit;
  64. }
  65. /**
  66. * 获取数据库实例
  67. * @return DB
  68. */
  69. function M(){
  70. $dbConf = C(array('DB_HOST','DB_PORT','DB_USER','DB_PWD','DB_NAME','DB_CHARSET'));
  71. return DB::getInstance($dbConf);
  72. }
  73. /**
  74. * 如果文件存在就include进来
  75. * @param string $path 文件路径
  76. * @return void
  77. */
  78. function includeIfExist($path){
  79. if(file_exists($path)){
  80. include $path;
  81. }
  82. }
  83. /**
  84. * 总控类
  85. */
  86. class SinglePHP {
  87. /**
  88. * 控制器
  89. * @var string
  90. */
  91. private $c;
  92. /**
  93. * Action
  94. * @var string
  95. */
  96. private $a;
  97. /**
  98. * 单例
  99. * @var SinglePHP
  100. */
  101. private static $_instance;
  102. /**
  103. * 构造函数,初始化配置
  104. * @param array $conf
  105. */
  106. private function __construct($conf){
  107. C($conf);
  108. }
  109. private function __clone(){}
  110. /**
  111. * 获取单例
  112. * @param array $conf
  113. * @return SinglePHP
  114. */
  115. public static function getInstance($conf){
  116. if(!(self::$_instance instanceof self)){
  117. self::$_instance = new self($conf);
  118. }
  119. return self::$_instance;
  120. }
  121. /**
  122. * 运行应用实例
  123. * @access public
  124. * @return void
  125. */
  126. public function run(){
  127. if(C('USE_SESSION') == true){
  128. session_start();
  129. }
  130. C('APP_FULL_PATH', getcwd().'/'.C('APP_PATH').'/');
  131. includeIfExist( C('APP_FULL_PATH').'/common.php');
  132. $pathMod = C('PATH_MOD');
  133. $pathMod = empty($pathMod)?'NORMAL':$pathMod;
  134. spl_autoload_register(array('SinglePHP', 'autoload'));
  135. if(strcmp(strtoupper($pathMod),'NORMAL') === 0 || !isset($_SERVER['PATH_INFO'])){
  136. $this->c = isset($_GET['c'])?$_GET['c']:'Index';
  137. $this->a = isset($_GET['a'])?$_GET['a']:'Index';
  138. }else{
  139. $pathInfo = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:'';
  140. $pathInfoArr = explode('/',trim($pathInfo,'/'));
  141. if(isset($pathInfoArr[0]) && $pathInfoArr[0] !== ''){
  142. $this->c = $pathInfoArr[0];
  143. }else{
  144. $this->c = 'Index';
  145. }
  146. if(isset($pathInfoArr[1])){
  147. $this->a = $pathInfoArr[1];
  148. }else{
  149. $this->a = 'Index';
  150. }
  151. }
  152. if(!class_exists($this->c.'Controller')){
  153. halt('控制器'.$this->c.'不存在');
  154. }
  155. $controllerClass = $this->c.'Controller';
  156. $controller = new $controllerClass();
  157. if(!method_exists($controller, $this->a.'Action')){
  158. halt('方法'.$this->a.'不存在');
  159. }
  160. call_user_func(array($controller,$this->a.'Action'));
  161. }
  162. /**
  163. * 自动加载函数
  164. * @param string $class 类名
  165. */
  166. public static function autoload($class){
  167. if(substr($class,-10)=='Controller'){
  168. includeIfExist(C('APP_FULL_PATH').'/Controller/'.$class.'.class.php');
  169. }elseif(substr($class,-6)=='Widget'){
  170. includeIfExist(C('APP_FULL_PATH').'/Widget/'.$class.'.class.php');
  171. }else{
  172. includeIfExist(C('APP_FULL_PATH').'/Lib/'.$class.'.class.php');
  173. }
  174. }
  175. }
  176. /**
  177. * 控制器类
  178. */
  179. class Controller {
  180. /**
  181. * 视图实例
  182. * @var View
  183. */
  184. private $_view;
  185. /**
  186. * 构造函数,初始化视图实例,调用hook
  187. */
  188. public function __construct(){
  189. $this->_view = new View();
  190. $this->_init();
  191. }
  192. /**
  193. * 前置hook
  194. */
  195. protected function _init(){}
  196. /**
  197. * 渲染模板并输出
  198. * @param null|string $tpl 模板文件路径
  199. * 参数为相对于App/View/文件的相对路径,不包含后缀名,例如index/index
  200. * 如果参数为空,则默认使用$controller/$action.php
  201. * 如果参数不包含"/",则默认使用$controller/$tpl
  202. * @return void
  203. */
  204. protected function display($tpl=''){
  205. if($tpl === ''){
  206. $trace = debug_backtrace();
  207. $controller = substr($trace[1]['class'], 0, -10);
  208. $action = substr($trace[1]['function'], 0 , -6);
  209. $tpl = $controller . '/' . $action;
  210. }elseif(strpos($tpl, '/') === false){
  211. $trace = debug_backtrace();
  212. $controller = substr($trace[1]['class'], 0, -10);
  213. $tpl = $controller . '/' . $tpl;
  214. }
  215. $this->_view->display($tpl);
  216. }
  217. /**
  218. * 为视图引擎设置一个模板变量
  219. * @param string $name 要在模板中使用的变量名
  220. * @param mixed $value 模板中该变量名对应的值
  221. * @return void
  222. */
  223. protected function assign($name,$value){
  224. $this->_view->assign($name,$value);
  225. }
  226. /**
  227. * 将数据用json格式输出至浏览器,并停止执行代码
  228. * @param array $data 要输出的数据
  229. */
  230. protected function ajaxReturn($data){
  231. echo json_encode($data);
  232. exit;
  233. }
  234. /**
  235. * 重定向至指定url
  236. * @param string $url 要跳转的url
  237. * @param void
  238. */
  239. protected function redirect($url){
  240. header("Location: $url");
  241. exit;
  242. }
  243. }
  244. /**
  245. * 视图类
  246. */
  247. class View {
  248. /**
  249. * 视图文件目录
  250. * @var string
  251. */
  252. private $_tplDir;
  253. /**
  254. * 视图文件路径
  255. * @var string
  256. */
  257. private $_viewPath;
  258. /**
  259. * 视图变量列表
  260. * @var array
  261. */
  262. private $_data = array();
  263. /**
  264. * 给tplInclude用的变量列表
  265. * @var array
  266. */
  267. private static $tmpData;
  268. /**
  269. * @param string $tplDir
  270. */
  271. public function __construct($tplDir=''){
  272. if($tplDir == ''){
  273. $this->_tplDir = './'.C('APP_PATH').'/View/';
  274. }else{
  275. $this->_tplDir = $tplDir;
  276. }
  277. }
  278. /**
  279. * 为视图引擎设置一个模板变量
  280. * @param string $key 要在模板中使用的变量名
  281. * @param mixed $value 模板中该变量名对应的值
  282. * @return void
  283. */
  284. public function assign($key, $value) {
  285. $this->_data[$key] = $value;
  286. }
  287. /**
  288. * 渲染模板并输出
  289. * @param null|string $tplFile 模板文件路径,相对于App/View/文件的相对路径,不包含后缀名,例如index/index
  290. * @return void
  291. */
  292. public function display($tplFile) {
  293. $this->_viewPath = $this->_tplDir . $tplFile . '.php';
  294. unset($tplFile);
  295. extract($this->_data);
  296. include $this->_viewPath;
  297. }
  298. /**
  299. * 用于在模板文件中包含其他模板
  300. * @param string $path 相对于View目录的路径
  301. * @param array $data 传递给子模板的变量列表,key为变量名,value为变量值
  302. * @return void
  303. */
  304. public static function tplInclude($path, $data=array()){
  305. self::$tmpData = array(
  306. 'path' => C('APP_FULL_PATH') . '/View/' . $path . '.php',
  307. 'data' => $data,
  308. );
  309. unset($path);
  310. unset($data);
  311. extract(self::$tmpData['data']);
  312. include self::$tmpData['path'];
  313. }
  314. }
  315. /**
  316. * Widget类
  317. * 使用时需继承此类,重写invoke方法,并在invoke方法中调用display
  318. */
  319. class Widget {
  320. /**
  321. * 视图实例
  322. * @var View
  323. */
  324. protected $_view;
  325. /**
  326. * Widget名
  327. * @var string
  328. */
  329. protected $_widgetName;
  330. /**
  331. * 构造函数,初始化视图实例
  332. */
  333. public function __construct(){
  334. $this->_widgetName = get_class($this);
  335. $dir = C('APP_FULL_PATH') . '/Widget/Tpl/';
  336. $this->_view = new View($dir);
  337. }
  338. /**
  339. * 处理逻辑
  340. * @param mixed $data 参数
  341. */
  342. public function invoke($data){}
  343. /**
  344. * 渲染模板
  345. * @param string $tpl 模板路径,如果为空则用类名作为模板名
  346. */
  347. protected function display($tpl=''){
  348. if($tpl == ''){
  349. $tpl = $this->_widgetName;
  350. }
  351. $this->_view->display($tpl);
  352. }
  353. /**
  354. * 为视图引擎设置一个模板变量
  355. * @param string $name 要在模板中使用的变量名
  356. * @param mixed $value 模板中该变量名对应的值
  357. * @return void
  358. */
  359. protected function assign($name,$value){
  360. $this->_view->assign($name,$value);
  361. }
  362. }
  363. /**
  364. * 数据库操作类
  365. * 使用方法:
  366. * DB::getInstance($conf)->query('select * from table');
  367. * 其中$conf是一个关联数组,需要包含以下key:
  368. * DB_HOST DB_USER DB_PWD DB_NAME
  369. * 可以用DB_PORT和DB_CHARSET来指定端口和编码,默认3306和utf8
  370. */
  371. class DB {
  372. /**
  373. * 数据库链接
  374. * @var resource
  375. */
  376. private $_db;
  377. /**
  378. * 保存最后一条sql
  379. * @var string
  380. */
  381. private $_lastSql;
  382. /**
  383. * 上次sql语句影响的行数
  384. * @var int
  385. */
  386. private $_rows;
  387. /**
  388. * 上次sql执行的错误
  389. * @var string
  390. */
  391. private $_error;
  392. /**
  393. * 实例数组
  394. * @var array
  395. */
  396. private static $_instance = array();
  397. /**
  398. * 构造函数
  399. * @param array $dbConf 配置数组
  400. */
  401. private function __construct($dbConf){
  402. if(!isset($dbConf['DB_CHARSET'])){
  403. $dbConf['DB_CHARSET'] = 'utf8';
  404. }
  405. $this->_db = mysql_connect($dbConf['DB_HOST'].':'.$dbConf['DB_PORT'],$dbConf['DB_USER'],$dbConf['DB_PWD']);
  406. if($this->_db === false){
  407. halt(mysql_error());
  408. }
  409. $selectDb = mysql_select_db($dbConf['DB_NAME'],$this->_db);
  410. if($selectDb === false){
  411. halt(mysql_error());
  412. }
  413. mysql_set_charset($dbConf['DB_CHARSET']);
  414. }
  415. private function __clone(){}
  416. /**
  417. * 获取DB类
  418. * @param array $dbConf 配置数组
  419. * @return DB
  420. */
  421. static public function getInstance($dbConf){
  422. if(!isset($dbConf['DB_PORT'])){
  423. $dbConf['DB_PORT'] = '3306';
  424. }
  425. $key = $dbConf['DB_HOST'].':'.$dbConf['DB_PORT'];
  426. if(!isset(self::$_instance[$key]) || !(self::$_instance[$key] instanceof self)){
  427. self::$_instance[$key] = new self($dbConf);
  428. }
  429. return self::$_instance[$key];
  430. }
  431. /**
  432. * 转义字符串
  433. * @param string $str 要转义的字符串
  434. * @return string 转义后的字符串
  435. */
  436. public function escape($str){
  437. return mysql_real_escape_string($str, $this->_db);
  438. }
  439. /**
  440. * 查询,用于select语句
  441. * @param string $sql 要查询的sql
  442. * @return bool|array 查询成功返回对应数组,失败返回false
  443. */
  444. public function query($sql){
  445. $this->_rows = 0;
  446. $this->_error = '';
  447. $this->_lastSql = $sql;
  448. $this->logSql();
  449. $res = mysql_query($sql,$this->_db);
  450. if($res === false){
  451. $this->_error = mysql_error($this->_db);
  452. $this->logError();
  453. return false;
  454. }else{
  455. $this->_rows = mysql_num_rows($res);
  456. $result = array();
  457. if($this->_rows >0) {
  458. while($row = mysql_fetch_array($res, MYSQL_ASSOC)){
  459. $result[] = $row;
  460. }
  461. mysql_data_seek($res,0);
  462. }
  463. return $result;
  464. }
  465. }
  466. /**
  467. * 查询,用于insert/update/delete语句
  468. * @param string $sql 要查询的sql
  469. * @return bool|int 查询成功返回影响的记录数量,失败返回false
  470. */
  471. public function execute($sql) {
  472. $this->_rows = 0;
  473. $this->_error = '';
  474. $this->_lastSql = $sql;
  475. $this->logSql();
  476. $result = mysql_query($sql, $this->_db) ;
  477. if ( false === $result) {
  478. $this->_error = mysql_error($this->_db);
  479. $this->logError();
  480. return false;
  481. } else {
  482. $this->_rows = mysql_affected_rows($this->_db);
  483. return $this->_rows;
  484. }
  485. }
  486. /**
  487. * 获取上一次查询影响的记录数量
  488. * @return int 影响的记录数量
  489. */
  490. public function getRows(){
  491. return $this->_rows;
  492. }
  493. /**
  494. * 获取上一次insert后生成的自增id
  495. * @return int 自增ID
  496. */
  497. public function getInsertId() {
  498. return mysql_insert_id($this->_db);
  499. }
  500. /**
  501. * 获取上一次查询的sql
  502. * @return string sql
  503. */
  504. public function getLastSql(){
  505. return $this->_lastSql;
  506. }
  507. /**
  508. * 获取上一次查询的错误信息
  509. * @return string 错误信息
  510. */
  511. public function getError(){
  512. return $this->_error;
  513. }
  514. /**
  515. * 记录sql到文件
  516. */
  517. private function logSql(){
  518. Log::sql($this->_lastSql);
  519. }
  520. /**
  521. * 记录错误日志到文件
  522. */
  523. private function logError(){
  524. $str = '[SQL ERR]'.$this->_error.' SQL:'.$this->_lastSql;
  525. Log::warn($str);
  526. }
  527. }
  528. /**
  529. * 日志类
  530. * 使用方法:Log::fatal('error msg');
  531. * 保存路径为 App/Log,按天存放
  532. * fatal和warning会记录在.log.wf文件中
  533. */
  534. class Log{
  535. /**
  536. * 打日志,支持SAE环境
  537. * @param string $msg 日志内容
  538. * @param string $level 日志等级
  539. * @param bool $wf 是否为错误日志
  540. */
  541. public static function write($msg, $level='DEBUG', $wf=false){
  542. if(function_exists('sae_debug')){ //如果是SAE,则使用sae_debug函数打日志
  543. $msg = "[{$level}]".$msg;
  544. sae_set_display_errors(false);
  545. sae_debug(trim($msg));
  546. sae_set_display_errors(true);
  547. }else{
  548. $msg = date('[ Y-m-d H:i:s ]')."[{$level}]".$msg."\r\n";
  549. $logPath = C('APP_FULL_PATH').'/Log/'.date('Ymd').'.log';
  550. if($wf){
  551. $logPath .= '.wf';
  552. }
  553. file_put_contents($logPath, $msg, FILE_APPEND);
  554. }
  555. }
  556. /**
  557. * 打印fatal日志
  558. * @param string $msg 日志信息
  559. */
  560. public static function fatal($msg){
  561. self::write($msg, 'FATAL', true);
  562. }
  563. /**
  564. * 打印warning日志
  565. * @param string $msg 日志信息
  566. */
  567. public static function warn($msg){
  568. self::write($msg, 'WARN', true);
  569. }
  570. /**
  571. * 打印notice日志
  572. * @param string $msg 日志信息
  573. */
  574. public static function notice($msg){
  575. self::write($msg, 'NOTICE');
  576. }
  577. /**
  578. * 打印debug日志
  579. * @param string $msg 日志信息
  580. */
  581. public static function debug($msg){
  582. self::write($msg, 'DEBUG');
  583. }
  584. /**
  585. * 打印sql日志
  586. * @param string $msg 日志信息
  587. */
  588. public static function sql($msg){
  589. self::write($msg, 'SQL');
  590. }
  591. }
  592. /**
  593. * ExtException类,记录额外的异常信息
  594. */
  595. class ExtException extends Exception{
  596. /**
  597. * @var array
  598. */
  599. protected $extra;
  600. /**
  601. * @param string $message
  602. * @param array $extra
  603. * @param int $code
  604. * @param null $previous
  605. */
  606. public function __construct($message = "", $extra = array(), $code = 0, $previous = null){
  607. $this->extra = $extra;
  608. parent::__construct($message, $code, $previous);
  609. }
  610. /**
  611. * 获取额外的异常信息
  612. * @return array
  613. */
  614. public function getExtra(){
  615. return $this->extra;
  616. }
  617. }
复制代码


PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号