搜索

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


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
PHP记录:PHP日志分析的最佳实践PHP记录:PHP日志分析的最佳实践Mar 10, 2025 pm 02:32 PM

PHP日志记录对于监视和调试Web应用程序以及捕获关键事件,错误和运行时行为至关重要。它为系统性能提供了宝贵的见解,有助于识别问题并支持更快的故障排除

在Laravel中使用Flash会话数据在Laravel中使用Flash会话数据Mar 12, 2025 pm 05:08 PM

Laravel使用其直观的闪存方法简化了处理临时会话数据。这非常适合在您的应用程序中显示简短的消息,警报或通知。 默认情况下,数据仅针对后续请求: $请求 -

php中的卷曲:如何在REST API中使用PHP卷曲扩展php中的卷曲:如何在REST API中使用PHP卷曲扩展Mar 14, 2025 am 11:42 AM

PHP客户端URL(curl)扩展是开发人员的强大工具,可以与远程服务器和REST API无缝交互。通过利用Libcurl(备受尊敬的多协议文件传输库),PHP curl促进了有效的执行

简化的HTTP响应在Laravel测试中模拟了简化的HTTP响应在Laravel测试中模拟了Mar 12, 2025 pm 05:09 PM

Laravel 提供简洁的 HTTP 响应模拟语法,简化了 HTTP 交互测试。这种方法显着减少了代码冗余,同时使您的测试模拟更直观。 基本实现提供了多种响应类型快捷方式: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

在Codecanyon上的12个最佳PHP聊天脚本在Codecanyon上的12个最佳PHP聊天脚本Mar 13, 2025 pm 12:08 PM

您是否想为客户最紧迫的问题提供实时的即时解决方案? 实时聊天使您可以与客户进行实时对话,并立即解决他们的问题。它允许您为您的自定义提供更快的服务

解释PHP中晚期静态结合的概念。解释PHP中晚期静态结合的概念。Mar 21, 2025 pm 01:33 PM

文章讨论了PHP 5.3中引入的PHP中的晚期静态结合(LSB),从而允许静态方法的运行时分辨率调用以获得更灵活的继承。 LSB的实用应用和潜在的触摸

自定义/扩展框架:如何添加自定义功能。自定义/扩展框架:如何添加自定义功能。Mar 28, 2025 pm 05:12 PM

本文讨论了将自定义功能添加到框架上,专注于理解体系结构,识别扩展点以及集成和调试的最佳实践。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。