Home Backend Development PHP Tutorial Super simple PHPMVC

Super simple PHPMVC

Jul 25, 2016 am 08:47 AM

Use native PHP syntax to render pages and provide widget functions.
  1. /**
  2. * Obtaining and setting configuration parameters supports batch definition
  3. * If $key is an associative array, the configuration will be written in the form of K-V
  4. * If $key is a numeric index array, the corresponding configuration array will be returned
  5. * @param string |array $key configuration variable
  6. * @param array|null $value configuration 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)){ //If the incoming key is a string
  14. return isset($_config[$key])?$_config[$key]:null;
  15. }
  16. if(is_array($key)){
  17. if(array_keys($key) !== range(0, count($key) - 1)){ //If the incoming key is an associative array
  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( 'The parameters passed in are incorrect');
  32. }
  33. }
  34. return null;
  35. }
  36. /**
  37. * Call Widget
  38. * @param string $name widget name
  39. * @param array $data Variable list passed to widget, key is variable name, value is variable value
  40. * @return void
  41. */
  42. function W($name, $data = array()){
  43. $fullName = $name. 'Widget';
  44. if(!class_exists($fullName)){
  45. halt('Widget '.$name.' does not exist');
  46. }
  47. $widget = new $fullName();
  48. $widget->invoke ($data);
  49. }
  50. /**
  51. * Terminate program execution
  52. * @param string $str Termination reason
  53. * @param bool $display Whether to display the call stack, not displayed by default
  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. * Get database instance
  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. * If the file exists, include it
  77. * @param string $path file path
  78. * @return void
  79. */
  80. function includeIfExist($path){
  81. if(file_exists( $path)){
  82. include $path;
  83. }
  84. }
  85. /**
  86. * General control category
  87. */
  88. class SinglePHP {
  89. /**
  90. * controller
  91. * @var string
  92. */
  93. private $c;
  94. /**
  95. * Action
  96. * @var string
  97. */
  98. private $a;
  99. /**
  100. * Singleton
  101. * @var SinglePHP
  102. */
  103. private static $_instance;
  104. /**
  105. * Constructor, initialization configuration
  106. * @param array $conf
  107. */
  108. private function __construct($conf){
  109. C($conf);
  110. }
  111. private function __clone(){}
  112. /**
  113. * Get singleton
  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. * Run application instance
  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('Controller'.$this->c.'does not exist');
  156. }
  157. $controllerClass = $this->c.'Controller';
  158. $controller = new $controllerClass();
  159. if(!method_exists($controller, $this->a.'Action')){
  160. halt('method'.$this->a.'does not exist');
  161. }
  162. call_user_func(array($controller,$this->a.'Action'));
  163. }
  164. /**
  165. * Automatic loading function
  166. * @param string $class class name
  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. * Controller class
  180. */
  181. class Controller {
  182. /**
  183. * View instance
  184. * @var View
  185. */
  186. private $_view;
  187. /**
  188. * Constructor, initialize view instance, call hook
  189. */
  190. public function __construct(){
  191. $this->_view = new View();
  192. $this->_init();
  193. }
  194. /**
  195. * Pre-hook
  196. */
  197. protected function _init(){}
  198. /**
  199. * Render the template and output
  200. * @param null|string $tpl template file path
  201. * The parameter is the relative path relative to App/View/file, does not include the suffix name, such as index/index
  202. * If the parameter is empty, then $controller/$action.php is used by default
  203. * If the parameter does not contain "/", $controller/$tpl is used by default
  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. * Set a template variable for the view engine
  221. * @param string $name The variable name to be used in the template
  222. * @param mixed $value The value corresponding to the variable name in the template
  223. * @return void
  224. */
  225. protected function assign($name,$value){
  226. $this->_view->assign($name,$value);
  227. }
  228. /**
  229. * Output the data to the browser in json format and stop executing the code
  230. * @param array $data The data to be output
  231. */
  232. protected function ajaxReturn($data){
  233. echo json_encode($data);
  234. exit;
  235. }
  236. /**
  237. * Redirect to the specified url
  238. * @param string $url The url to be redirected
  239. * @param void
  240. */
  241. protected function redirect($url){
  242. header("Location: $url");
  243. exit;
  244. }
  245. }
  246. /**
  247. * View class
  248. */
  249. class View {
  250. /**
  251. * View file directory
  252. * @var string
  253. */
  254. private $_tplDir;
  255. /**
  256. * View file path
  257. * @var string
  258. */
  259. private $_viewPath;
  260. /**
  261. * View variable list
  262. * @var array
  263. */
  264. private $_data = array();
  265. /**
  266. * Variable list for 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. * Set a template variable for the view engine
  282. * @param string $key The variable name to be used in the template
  283. * @param mixed $value The value corresponding to the variable name in the template
  284. * @return void
  285. */
  286. public function assign($key, $value) {
  287. $this->_data[$key] = $value;
  288. }
  289. /**
  290. * Render the template and output
  291. * @param null|string $tplFile Template file path, relative path to App/View/file, does not include suffix name, such as 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. * Used to include other templates in the template file
  302. * @param string $path The path relative to the View directory
  303. * @param array $data The variable list passed to the sub-template, key is the variable name, value is the variable 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 class
  319. * When using it, you need to inherit this class, rewrite the invoke method, and call display in the invoke method
  320. */
  321. class Widget {
  322. /**
  323. * View instance
  324. * @var View
  325. */
  326. protected $_view;
  327. /**
  328. * Widget name
  329. * @var string
  330. */
  331. protected $_widgetName;
  332. /**
  333. * Constructor, initialize view instance
  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. * Processing logic
  342. * @param mixed $data parameter
  343. */
  344. public function invoke($data){}
  345. /**
  346. * Render template
  347. * @param string $tpl template path, if it is empty, use the class name as the template name
  348. */
  349. protected function display($tpl=''){
  350. if($tpl == ''){
  351. $tpl = $this->_widgetName;
  352. }
  353. $this->_view->display($tpl);
  354. }
  355. /**
  356. * Set a template variable for the view engine
  357. * @param string $name The variable name to be used in the template
  358. * @param mixed $value The value corresponding to the variable name in the template
  359. * @return void
  360. */
  361. protected function assign($name,$value){
  362. $this->_view->assign($name,$value);
  363. }
  364. }
  365. /**
  366. * Database operation class
  367. * Usage method:
  368. * DB::getInstance($conf)->query('select * from table');
  369. * where $conf is an associative array and needs to contain the following keys:
  370. * DB_HOST DB_USER DB_PWD DB_NAME
  371. * You can use DB_PORT and DB_CHARSET to specify the port and encoding. The default is 3306 and utf8
  372. */
  373. class DB {
  374. /**
  375. * Database link
  376. * @var resource
  377. */
  378. private $_db;
  379. /**
  380. * Save the last sql
  381. * @var string
  382. */
  383. private $_lastSql;
  384. /**
  385. * The number of rows affected by the last sql statement
  386. * @var int
  387. */
  388. private $_rows;
  389. /**
  390. * Error in the last sql execution
  391. * @var string
  392. */
  393. private $_error;
  394. /**
  395. * Instance array
  396. * @var array
  397. */
  398. private static $_instance = array();
  399. /**
  400. * Constructor
  401. * @param array $dbConf configuration array
  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. * Get DB class
  420. * @param array $dbConf configuration array
  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. * Escaped string
  435. * @param string $str The string to be escaped
  436. * @return string The escaped string
  437. */
  438. public function escape($str){
  439. return mysql_real_escape_string($str, $this->_db);
  440. }
  441. /**
  442. * Query, used for select statements
  443. * @param string $sql The sql to be queried
  444. * @return bool|array If the query succeeds, it returns the corresponding array, if it fails, it returns 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. * Query, used for insert/update/delete statements
  470. * @param string $sql The sql to be queried
  471. * @return bool|int If the query succeeds, it returns the number of affected records, if it fails, it returns 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. * Get the number of records affected by the last query
  490. * @return int The number of records affected
  491. */
  492. public function getRows(){
  493. return $this->_rows;
  494. }
  495. /**
  496. * Get the auto-increment ID generated after the last insert
  497. * @return int Auto-increment ID
  498. */
  499. public function getInsertId() {
  500. return mysql_insert_id($this->_db);
  501. }
  502. /**
  503. * Get the sql of the last query
  504. * @return string sql
  505. */
  506. public function getLastSql(){
  507. return $this->_lastSql;
  508. }
  509. /**
  510. * Get the error information of the last query
  511. * @return string error information
  512. */
  513. public function getError(){
  514. return $this->_error;
  515. }
  516. /**
  517. * Record sql to file
  518. */
  519. private function logSql(){
  520. Log::sql($this->_lastSql);
  521. }
  522. /**
  523. * Record error log to file
  524. */
  525. private function logError(){
  526. $str = '[SQL ERR]'.$this->_error.' SQL:'.$this->_lastSql;
  527. Log::warn($str);
  528. }
  529. }
  530. /**
  531. * Log class
  532. * Usage method: Log::fatal('error msg');
  533. * The saving path is App/Log, stored by day
  534. * Fatal and warning will be recorded in the .log.wf file
  535. */
  536. class Log{
  537. /**
  538. * Logging, supports SAE environment
  539. * @param string $msg Log content
  540. * @param string $level Log level
  541. * @param bool $wf Whether it is an error log
  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."rn";
  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. * Print fatal log
  560. * @param string $msg Log information
  561. */
  562. public static function fatal($msg){
  563. self::write($msg, 'FATAL', true);
  564. }
  565. /**
  566. * Print warning log
  567. * @param string $msg Log information
  568. */
  569. public static function warn($msg){
  570. self::write($msg, 'WARN', true);
  571. }
  572. /**
  573. * Print notice log
  574. * @param string $msg Log information
  575. */
  576. public static function notice($msg){
  577. self::write($msg, 'NOTICE');
  578. }
  579. /**
  580. * Print debug log
  581. * @param string $msg Log information
  582. */
  583. public static function debug($msg){
  584. self::write($msg, 'DEBUG');
  585. }
  586. /**
  587. * Print sql log
  588. * @param string $msg Log information
  589. */
  590. public static function sql($msg){
  591. self::write($msg, 'SQL');
  592. }
  593. }
  594. /**
  595. * ExtException class, records additional exception information
  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. * Get additional exception information
  614. * @return array
  615. */
  616. public function getExtra(){
  617. return $this->extra;
  618. }
  619. }
复制代码


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Explain JSON Web Tokens (JWT) and their use case in PHP APIs. Explain JSON Web Tokens (JWT) and their use case in PHP APIs. Apr 05, 2025 am 12:04 AM

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

How does session hijacking work and how can you mitigate it in PHP? How does session hijacking work and how can you mitigate it in PHP? Apr 06, 2025 am 12:02 AM

Session hijacking can be achieved through the following steps: 1. Obtain the session ID, 2. Use the session ID, 3. Keep the session active. The methods to prevent session hijacking in PHP include: 1. Use the session_regenerate_id() function to regenerate the session ID, 2. Store session data through the database, 3. Ensure that all session data is transmitted through HTTPS.

Describe the SOLID principles and how they apply to PHP development. Describe the SOLID principles and how they apply to PHP development. Apr 03, 2025 am 12:04 AM

The application of SOLID principle in PHP development includes: 1. Single responsibility principle (SRP): Each class is responsible for only one function. 2. Open and close principle (OCP): Changes are achieved through extension rather than modification. 3. Lisch's Substitution Principle (LSP): Subclasses can replace base classes without affecting program accuracy. 4. Interface isolation principle (ISP): Use fine-grained interfaces to avoid dependencies and unused methods. 5. Dependency inversion principle (DIP): High and low-level modules rely on abstraction and are implemented through dependency injection.

How to debug CLI mode in PHPStorm? How to debug CLI mode in PHPStorm? Apr 01, 2025 pm 02:57 PM

How to debug CLI mode in PHPStorm? When developing with PHPStorm, sometimes we need to debug PHP in command line interface (CLI) mode...

How to automatically set permissions of unixsocket after system restart? How to automatically set permissions of unixsocket after system restart? Mar 31, 2025 pm 11:54 PM

How to automatically set the permissions of unixsocket after the system restarts. Every time the system restarts, we need to execute the following command to modify the permissions of unixsocket: sudo...

Explain late static binding in PHP (static::). Explain late static binding in PHP (static::). Apr 03, 2025 am 12:04 AM

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

How to send a POST request containing JSON data using PHP's cURL library? How to send a POST request containing JSON data using PHP's cURL library? Apr 01, 2025 pm 03:12 PM

Sending JSON data using PHP's cURL library In PHP development, it is often necessary to interact with external APIs. One of the common ways is to use cURL library to send POST�...

See all articles