• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 開發php框架入門

    標簽: php

    doopsPHP框架開發入門

    倉庫地址

    倉庫地址 https://gitee.com/gusijin/doopsPHP

    為什么要自己開發框架呢?

    • 發現比較好的設計用法
    • 在看文檔的同時思考實現原理
    • 自己實現,深刻理解
    • 功能可以一點點實現

    什么是MVC

    MVC是一個架構,或者說是一個設計模式,它就是強制性使應用程序的輸入,處理和輸出分開。將一個應用程序分為三個部分:Model,View,Controller。

    Model 模型(完成業務邏輯:由javaBean構成,在MVC的三個部件中,模型擁有最多的處理任務。例如它可能用象EJBs和javabean這樣的構件對象來處理數據庫。由于應用于模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復性。)

    View 視圖(就是負責跟用戶交互的界面。一般就是由HTML,css元素組成的界面,當然現在還有一些像js,ajax,flex一些也都屬于視圖層。 在視圖層里沒有真正的處理發生,之負責數據輸出,并允許用戶操縱的方式。MVC能為應用程序處理很多不同的視圖。 )

    Controller 控制器(接收請求—>調用模型—>根據結果派發頁面并經過模型處理返回相應數據 )

    在這里插入圖片描述

    環境準備

    • 最基本的PHP環境:
      Nginx或者openresty
      PHP5.4+ 及以上
      MySQL5.6

    目錄準備

    在開發前,給這個框架先起個名字吧,叫:doopsPHP。
    然后根據需要來把項目的目錄創建。
    假設我們建立的項目為 project,目錄結構就這樣:

        project                 WEB部署根目錄
        ├─app                   應用目錄
        │  ├─controller         控制器目錄
        │  ├─model              模塊目錄
        ├─config                配置文件目錄
        ├─public                公共目錄
        │  ├─themes              模板主題目錄
        │  ├─index.php           入口文件  
        ├─system                系統文件目錄
        ├─vendor                包管理目錄
        ├─env                   參數配置文件
    

    nginx配置

    nginx.conf文件
    配置要目錄到public

    location / {
    	root   /www/doopsPHP/public;
    	index  index.php index.html index.htm;
    	if (!-e $request_filename) {
    		rewrite  ^(.*)$  /index.php?s=/$1  last;
    		break;
    	}
    }
    location ~ \.php(.*)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /www/doopsPHP/public$fastcgi_script_name;
        include        fastcgi_params;
    }
    
    

    核心文件

    入口文件

    在 project 目錄public下新建 index.php 入口文件,文件內容為:

    <?php
    
    /**
     * doopsPHP
     * An open source application development framework for PHP
     * Copyright (c) 2019 - 2020, gusijin
     * @package    doopsPHP
     * @author    gusijin
     * @copyright    Copyright (c) 2019 - 2020, gusijin
     * @since    Version 1.0.1
     */
    
    
    if (version_compare(PHP_VERSION, '5.4.0', '<')) {
        die('require PHP > 5.4.0');
    };
    
    define('PUBLIC_PATH', str_replace('\\', DIRECTORY_SEPARATOR, __DIR__) . DIRECTORY_SEPARATOR);
    define("BASE_PATH", PUBLIC_PATH . '..' . DIRECTORY_SEPARATOR);
    define("SYSTEM_PATH", BASE_PATH . 'system' . DIRECTORY_SEPARATOR);
    define("APP_PATH", BASE_PATH . 'app' . DIRECTORY_SEPARATOR);
    define("CONF_PATH", BASE_PATH . 'config' . DIRECTORY_SEPARATOR);
    define("CORE_PATH", SYSTEM_PATH . 'core' . DIRECTORY_SEPARATOR);
    
    require CORE_PATH . 'run.php';
    
    

    配置文件

    數據庫配置
    env文件

    ···
    DEBUG = true

    DB_HOST = 127.0.0.1
    DB_PORT = 3306
    DB_USER = root
    DB_PWD = 123456
    DB_NAME = test
    DB_CHATSET = utf8
    ···

    自定義路由配置
    config/routes.php

    <?php
    /**
     * 自定義路由
     * User: gusijin
     * Date: 2019/6/25
     * Time: 17:09
     */
    
    return [
        'ROUTES' => [
            'shop.html' => ['action' => 'index/shop'],
        ],
    ];
    

    實例化類

    入口文件包含了run.php文件,
    實例化,調用bootstrap()方法

    system/core/run.php

    <?php
    
    namespace core;
    
    //引入公共函數
    require_once SYSTEM_PATH . 'common' . DIRECTORY_SEPARATOR . 'function.php';
    //引入自動加載類,并注冊自動加載函數
    require_once CORE_PATH . 'Loader.php';
    
    //公共函數解析配置
    spl_autoload_register('core\\Loader::autoLoad');
    
    Router::bootstrap();
    
    
    

    公共函數類

    system/common/function.php

    <?php
    
    if (!function_exists('createUrl')) {
        /**
         * 獲取url
         * @param string $info
         * @return string
         */
        function createUrl($info = '')
        {
            $url_info = explode(DIRECTORY_SEPARATOR, strtolower($info));
            $controller = isset($url_info[1]) ? $url_info[0] : strtolower(CONTROLLER);
            $action = isset($url_info[1]) ? $url_info[1] : $url_info[0];
            if (isset($_GET['r'])) {
                return DIRECTORY_SEPARATOR . 'index.php?r=' . $controller . DIRECTORY_SEPARATOR . $action;
            } else {
                return DIRECTORY_SEPARATOR . $controller . DIRECTORY_SEPARATOR . $action;
            }
        }
    }
    
    
    

    自動加載類

    system/core/Loader.php

    
    <?php
    
    namespace core;
    
    use Whoops;
    
    class Loader
    {
        public static function autoLoad($class)
        {
            $vendorAutoloadFile = BASE_PATH . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
            if (file_exists($vendorAutoloadFile)) {
                include $vendorAutoloadFile;
            }
    
            $class = ltrim($class, '\\');
            $class_path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
            if (file_exists(SYSTEM_PATH . $class_path)) {
                include SYSTEM_PATH . $class_path;
    
                //bug調試
                if (Env::get('DEBUG')) {
                    $whoops = new Whoops\Run;
                    $whoops->pushHandler(new Whoops\Handler\PrettyPageHandler);
                    $whoops->register();
                }
    
                return true;
            }
            if (file_exists(APP_PATH . $class_path)) {
                include APP_PATH . $class_path;
                return true;
            }
        }
    
    }
    

    env配置類

    system/core/Env.php

    <?php
    
    namespace core;
    
    class Env
    {
        private static $env = null;
        private static $envFile = 'env';
    
        public static function reload()
        {
            $envFile = BASE_PATH . self::$envFile;
            if (is_file($envFile)) {
                self::$env = parse_ini_file($envFile, true);
            } else {
                echo 'env file is not exist';
                exit();
            }
        }
    
        /**
         * 讀取env配置
         * @param string $key
         * @return string|null
         */
        public static function get($key, $default = null)
        {
            if (is_null(self::$env)) {
                self::reload();
            }
            return isset(self::$env[$key]) ? self::$env[$key] : $default;
        }
    }
    
    

    路由解析類

    system/core/Router.php

    <?php
    
    namespace core;
    class Router
    {
        public static $uri;
        protected static $contrallerName;
        protected static $actionName;
    
        /**
         * 路由解析方法選擇
         */
        public static function bootstrap()
        {
            self::setDebug();
    
            self::$uri = $_SERVER['REQUEST_URI'];
            if (isset($_GET['r'])) {
                self::parseByCommonRouter();
            } else {
                self::parseRewrite();
            }
    
            self::boot();
        }
    
        /**
         * 普通路由解析
         */
        public static function parseByCommonRouter()
        {
            $router = isset($_GET['r']) ? explode(DIRECTORY_SEPARATOR, $_GET['r']) : ['index', 'index'];
    
            self::$contrallerName = ucfirst(strtolower($router[0]));
            self::$actionName = isset($router[1]) ? strtolower($router[1]) : Env::get('DEFAULT_ACTION');
        }
    
        /**
         * URL重寫路由解析
         */
        public static function parseRewrite()
        {
    
    
            if (strpos(self::$uri, "?")) {
                $router = substr(self::$uri, 0, strpos(self::$uri, "?"));
            } else {
                $router = self::$uri;
            }
            if ($router == DIRECTORY_SEPARATOR) {
                $router = ['index', 'index'];
            }
            is_string($router) && $routerUri = trim($router, DIRECTORY_SEPARATOR);
    
            //自定義路徑
            $routersArr = require CONF_PATH . 'routes.php';
            if (!empty($routerUri) && !empty($routersArr['ROUTES'][$routerUri])) {
                $routerUri = $routersArr['ROUTES'][$routerUri]['action'];
            }
            !is_array($router) && $router = explode(DIRECTORY_SEPARATOR, $routerUri);
    
            self::$contrallerName = ucfirst(strtolower($router[0]));
            self::$actionName = isset($router[1]) ? strtolower($router[1]) : Env::get('DEFAULT_ACTION');
        }
    
        /**
         * 路由執行
         */
        public static function boot()
        {
    
            define('CONTROLLER', self::$contrallerName);
            define('ACTION', self::$contrallerName);
            define('LOCAL_URL', createUrl(self::$contrallerName . DIRECTORY_SEPARATOR . self::$actionName));
    
            $controllerName = 'controller\\' . self::$contrallerName;
            if (!class_exists($controllerName)) {
                echo self::$contrallerName . " does not defined";
                exit();
            }
            $controller = new $controllerName();
            if (!method_exists($controller, self::$actionName)) {
                echo self::$actionName . " does not defined";
                exit();
            }
            call_user_func([
                $controller,
                self::$actionName,
            ]);
        }
    
    
        private static function setDebug()
        {
            if (Env::get('DEBUG')) {
                ini_set('display_errors', 1);
                error_reporting(-1);
            } else {
                ini_set('display_errors', 0);
            }
        }
    
    }
    

    Controller基類

    system/core/Controller.php

    
    <?php
    
    namespace core;
    abstract class Controller
    {
    
        protected function render($viewFile, $data = null)
        {
            View::display($viewFile, $data);
        }
    
        public function assign($tplVar, $value = '')
        {
            View::assign($tplVar, $value);
        }
    }
    

    Model基類

    system/core/Model.php

    <?php
    
    namespace core;
    abstract class Model
    {
    }
    
    

    View基類

    system/core/View.php

    <?php
    
    namespace core;
    class View
    {
        private static $templateFile;
        public static $_var = array();
        public static $_foreachmark = '';
        public static $_foreach = array();
        public static $_temp_key = array(); // 臨時存放 foreach 里 key 的數組
        public static $_temp_val = array(); // 臨時存放 foreach 里 item 的數組
        public static $_patchstack = '';
        public static $_nowtime = null;
    
        function __construct()
        {
            self::$_nowtime = time();
            header('Content-type: text/html; charset=utf-8');
        }
    
    
        /**
         * 展示頁面
         * @param $viewFile
         * @param $data
         */
        public static function display($viewFile, $data)
        {
            //賦值給變量self::$_var
            if (is_array($data)) {
                foreach ($data as $datakey => $dataValue) {
                    if ($dataValue != '') {
                        self::assign($datakey, $dataValue);
                    }
                }
            }
    
            $content = self::fetch($viewFile);
    
            echo $content;
        }
    
        private static function fetch($viewFile)
        {
    
            $filename = self::checkTemplate($viewFile);
            $content = self::makeCompiled($filename);
            return $content;
        }
    
        /**
         * 編譯模板函數
         * @access  public
         * @param   string $filename
         * @return  sring        編譯后文件地址
         */
        private static function makeCompiled($filename)
        {
            $source = '';
            if (file_exists($filename)) {
                $source = self::fetchStr(@file_get_contents($filename));
    
                $source = self::_eval($source);
                //$source = self::_require($source);
            }
            return $source;
        }
    
        private static function _eval($content)
        {
            ob_start();
            eval('?' . '>' . trim($content));
            $content = ob_get_contents();
            ob_end_clean();
    
            return $content;
        }
    
        /**
         * 處理字符串函數
         * @access  public
         * @param   string $source
         * @return  sring
         */
        private static function fetchStr($source)
        {
            //return preg_replace("/{([^\}\{\n]*)}/e", "\self::select('\\1');", $source);
            return preg_replace_callback("/{([^\}\{\n]*)}/", function ($r) {
                return self::select($r[1]);
            }, $source);
        }
    
        /**
         * 處理{}標簽
         * @access  public
         * @param   string $tag
         * @return  sring
         */
        private static function select($tag)
        {
            $tag = stripslashes(trim($tag));
    
            if (empty($tag)) {
                return '{}';
            } elseif ($tag{0} == '*' && substr($tag, -1) == '*') {
                // 注釋部分
                return '';
            } elseif ($tag{0} == '$') {
                // 變量
                return '<?php echo ' . self::get_val(substr($tag, 1)) . '; ?>';
            } elseif ($tag{0} == '/') {
                // 結束 tag
                switch (substr($tag, 1)) {
                    case 'if':
                        return '<?php endif; ?>';
                        break;
    
                    case 'foreach':
                        if (self::$_foreachmark == 'foreachelse') {
                            $output = '<?php endif; unset($_from); ?>';
                        } else {
                            array_pop(self::$_patchstack);
                            $output = '<?php endforeach; endif; unset($_from); ?>';
                        }
                        $output .= "<?php self::pop_vars(); ?>";
    
                        return $output;
                        break;
    
                    case 'literal':
                        return '';
                        break;
    
                    default:
                        return '{' . $tag . '}';
                        break;
                }
            } else {
                $tag_array = explode(' ', $tag);
                $tag_sel = array_shift($tag_array);
                switch ($tag_sel) {
                    case 'if':
                        return self::_compileIfTag(substr($tag, 3));
                        break;
    
                    case 'else':
                        return '<?php else: ?>';
                        break;
    
                    case 'elseif':
                        return self::_compileIfTag(substr($tag, 7), true);
                        break;
    
                    case 'foreachelse':
                        self::$_foreachmark = 'foreachelse';
                        return '<?php endforeach; else: ?>';
                        break;
    
                    case 'foreach':
                        self::$_foreachmark = 'foreach';
                        if (!isset(self::$_patchstack)) {
                            self::$_patchstack = array();
                        }
                        return self::_compileForeachStart(substr($tag, 8));
                        break;
    
                    case 'assign':
                        $t = self::getPara(substr($tag, 7), 0);
    
                        if ($t['value']{0} == '$') {
                            /* 如果傳進來的值是變量,就不用用引號 */
                            $tmp = 'self::assign(\'' . $t['var'] . '\',' . $t['value'] . ');';
                        } else {
                            $tmp = 'self::assign(\'' . $t['var'] . '\',\'' . addcslashes($t['value'], "'") . '\');';
                        }
    
                        return '<?php ' . $tmp . ' ?>';
                        break;
    
                    case 'include':
                        $t = self::getPara(substr($tag, 8), 0);
    
                        if (substr($t[file], -4, 4) != 'html') {
                            $code = var_export(self::$_var[$t['inc_var']], 1);
                            if ($t['inc_var']) {
                                return '<?php self::assign(\'inc_var\',' . $code . ');echo self::fetch(' . "$t[file]" . '); ?>';
                            } else {
                                return '<?php echo self::fetch(' . "$t[file]" . '); ?>';
                            }
    
                        } else {
                            $code = var_export(self::$_var[$t['inc_var']], 1);
                            if ($t['inc_var'])
                                return '<?php self::assign(\'inc_var\',' . $code . ');echo self::fetch(' . "'$t[file]'" . '); ?>';
                            else
                                return '<?php echo self::fetch(' . "'$t[file]'" . '); ?>';
                        }
    
    
                        break;
    
                    case 'insert_scripts':
                        $t = self::getPara(substr($tag, 15), 0);
    
                        return '<?php echo self::smarty_insert_scripts(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'create_pages':
                        $t = self::getPara(substr($tag, 13), 0);
    
                        return '<?php echo self::smarty_create_pages(' . self::makeArray($t) . '); ?>';
                        break;
                    case 'insert' :
                        $t = self::getPara(substr($tag, 7), false);
                        $out = "<?php \n" . '$k = ' . preg_replace("/(\'\\$[^,]+)/e", "stripslashes(trim('\\1','\''));", var_export($t, true)) . ";\n";
                        $out .= 'echo $k[\'name\'] . \'|\' . base64_encode(serialize($k));' . "\n?>";
    
                        return $out;
                        break;
    
                    case 'literal':
                        return '';
                        break;
    
                    case 'cycle' :
                        $t = self::getPara(substr($tag, 6), 0);
    
                        return '<?php echo self::cycle(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'html_options':
                        $t = self::getPara(substr($tag, 13), 0);
    
                        return '<?php echo self::html_options(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'html_select_date':
                        $t = self::getPara(substr($tag, 17), 0);
    
                        return '<?php echo self::html_select_date(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'html_radios':
                        $t = self::getPara(substr($tag, 12), 0);
    
                        return '<?php echo self::html_radios(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'html_select_time':
                        $t = self::getPara(substr($tag, 12), 0);
    
                        return '<?php echo self::html_select_time(' . self::makeArray($t) . '); ?>';
                        break;
    
                    case 'function' :
                        $t = self::getPara(substr($tag, 8), false);
    
                        $out = "<?php \n" . '$k = ' . preg_replace("/(\'\\$[^,]+)/e", "stripslashes(trim('\\1','\''));", var_export($t, true)) . ";\n";
                        $out .= 'echo $k[\'name\'](';
    
                        $first = true;
    
                        foreach ($t as $n => $v) {
                            if ($n != "name") {
                                if ($first) {
                                    $out .= '$k[\'' . $n . '\']';
                                    $first = false;
                                } else {
                                    $out .= ',$k[\'' . $n . '\']';
                                }
                            }
                        }
                        $out .= ');' . "\n?>";
    
                        return $out;
                        break;
                    case 'url_wap' :
                        $reg_text = "/\"([^\"]+)\"/";
                        preg_match_all($reg_text, $tag, $matches);
                        if (count($matches[0]) > 0) {
                            //url格式正確
                            $param_str = "\"\"";
                            if (isset($matches[0][1]) && $matches[0][1] != '') {
                                //有額外傳參
                                preg_match_all("/[$]([^\"&]+)/", $matches[0][1], $param_matches);
                                $replacement = array();
                                $finder = array();
                                if (count($param_matches[0]) > 0) {
                                    foreach ($param_matches[0] as $m_item) {
                                        $finder[] = $m_item;
                                    }
                                    //有參數
                                    foreach ($param_matches[1] as $p_item) {
                                        $p_item_arr = explode(".", $p_item);
                                        $var_str = '".self::$_var';
                                        foreach ($p_item_arr as $var_item) {
                                            $var_str = $var_str . "['" . $var_item . "']";
                                        }
                                        $var_str .= '."';
                                        $replacement[] = $var_str;
                                    }
                                }
                                $param_str = str_replace($finder, $replacement, $matches[0][1]);
                            }
    
                            //$app_index = $matches[1][0];
                            $route = $matches[1][0];
                            if (empty($route))
                                $route = "index";
    
    
                            $code = "<?php\r\n";
                            $code .= "echo parse_url_tag_wap(\"";
                            $code .= "u:";
                            $code .= $route . "|\".";
                            $code .= $param_str . ".";
                            $code .= "\"\"); \r\n";
                            $code .= "?>";
    
                            return $code;
                        } else {
                            return '{' . $tag . '}';
                        }
    
                        break;
    
                    case 'url' :
                        $reg_text = "/\"([^\"]+)\"/";
                        preg_match_all($reg_text, $tag, $matches);
                        if (count($matches[0]) > 0) {
                            //url格式正確
                            $param_str = "\"\"";
                            if (isset($matches[0][1]) && $matches[0][1] != '') {
                                //有額外傳參
                                //return print_r($matches[0][2],true);
                                preg_match_all("/[$]([^\"&]+)/", $matches[0][1], $param_matches);
                                $replacement = array();
                                $finder = array();
                                if (count($param_matches[0]) > 0) {
                                    foreach ($param_matches[0] as $m_item) {
                                        $finder[] = $m_item;
                                    }
                                    //有參數
                                    foreach ($param_matches[1] as $p_item) {
                                        $p_item_arr = explode(".", $p_item);
                                        $var_str = '".self::$_var';
                                        foreach ($p_item_arr as $var_item) {
                                            $var_str = $var_str . "['" . $var_item . "']";
                                        }
                                        $var_str .= '."';
                                        $replacement[] = $var_str;
                                    }
                                }
                                $param_str = str_replace($finder, $replacement, $matches[0][1]);
                            }
    
                            //$app_index = $matches[1][0];
                            $route = $matches[1][0];
                            if (empty($route))
                                $route = "index";
    
    
                            $code = "<?php\r\n";
                            $code .= "echo parse_url_tag(\"";
                            $code .= "u:";
                            $code .= $route . "|\".";
                            $code .= $param_str . ".";
                            $code .= "\"\"); \r\n";
                            $code .= "?>";
    
                            return $code;
                        } else {
                            return '{' . $tag . '}';
                        }
    
                        break;
    
                    default:
                        return '{' . $tag . '}';
                        break;
                }
            }
        }
    
        /**
         * 處理smarty標簽中的變量標簽
         * @access  public
         * @param   string $val
         * @return  bool
         */
        private static function get_val($val)
        {
            if (strrpos($val, '[') !== false) {
                $val = preg_replace("/\[([^\[\]]*)\]/eis", "'.'.str_replace('$','\$','\\1')", $val);
            }
    
            if (strrpos($val, '|') !== false) {
                $moddb = explode('|', $val);
                $val = array_shift($moddb);
            }
    
            if (empty($val)) {
                return '';
            }
    
            if (strpos($val, '.$') !== false) {
                $all = explode('.$', $val);
    
                foreach ($all as $key => $val) {
                    $all[$key] = $key == 0 ? self::makeVar($val) : '[' . self::makeVar($val) . ']';
                }
                $p = implode('', $all);
            } else {
                $p = self::makeVar($val);
            }
    
            if (!empty($moddb)) {
                foreach ($moddb as $key => $mod) {
                    $s = explode(':', $mod);
                    switch ($s[0]) {
                        case 'escape':
                            $s[1] = trim($s[1], '"');
                            if ($s[1] == 'html') {
                                $p = 'htmlspecialchars(' . $p . ')';
                            } elseif ($s[1] == 'url') {
                                $p = 'urlencode(' . $p . ')';
                            } elseif ($s[1] == 'decode_url') {
                                $p = 'urldecode(' . $p . ')';
                            } elseif ($s[1] == 'quotes') {
                                $p = 'addslashes(' . $p . ')';
                            } elseif ($s[1] == 'u8_url') {
                                if (EC_CHARSET != 'utf-8') {
                                    $p = 'urlencode(ecs_iconv("' . EC_CHARSET . '", "utf-8",' . $p . '))';
                                } else {
                                    $p = 'urlencode(' . $p . ')';
                                }
                            } else {
                                $p = 'htmlspecialchars(' . $p . ')';
                            }
                            break;
    
                        case 'nl2br':
                            $p = 'nl2br(' . $p . ')';
                            break;
    
                        case 'default':
                            $s[1] = $s[1]{0} == '$' ? self::get_val(substr($s[1], 1)) : "'$s[1]'";
                            $p = 'empty(' . $p . ') ? ' . $s[1] . ' : ' . $p;
                            break;
    
                        case 'truncate':
                            $p = 'sub_str(' . $p . ",$s[1])";
                            break;
    
                        case 'strip_tags':
                            $p = 'strip_tags(' . $p . ')';
                            break;
    
                        default:
                            # code...
                            break;
                    }
                }
            }
    
            return $p;
        }
    
    
        /**
         * 處理去掉$的字符串
         * @access  public
         * @param   string $val
         * @return  bool
         */
        private static function makeVar($val)
        {
            if (strrpos($val, '.') === false) {
                if (isset(self::$_var[$val]) && isset(self::$_patchstack[$val])) {
                    $val = self::$_patchstack[$val];
                }
                $p = 'self::$_var[\'' . $val . '\']';
            } else {
                $t = explode('.', $val);
                $_var_name = array_shift($t);
                if (isset(self::$_var[$_var_name]) && isset(self::$_patchstack[$_var_name])) {
                    $_var_name = self::$_patchstack[$_var_name];
                }
                if ($_var_name == 'smarty') {
                    $p = self::_compileSmartyRef($t);
                } else {
                    $p = 'self::$_var[\'' . $_var_name . '\']';
                }
                foreach ($t as $val) {
                    $p .= '[\'' . $val . '\']';
                }
            }
    
            return $p;
        }
    
    
        /**
         * 處理insert外部函數/需要include運行的函數的調用數據
         *
         * @access  public
         * @param   string $val
         * @param   int $type
         *
         * @return  array
         */
        private static function getPara($val, $type = 1) // 處理insert外部函數/需要include運行的函數的調用數據
        {
            $pa = self::strTrim($val);
            foreach ($pa as $value) {
                if (strrpos($value, '=')) {
                    list($a, $b) = explode('=', str_replace(array(' ', '"', "'", '&quot;'), '', $value));
    
                    if ($b{0} == '$') {
                        if ($type) {
                            eval('$para[\'' . $a . '\']=' . self::get_val(substr($b, 1)) . ';');
                        } else {
                            $para[$a] = self::get_val(substr($b, 1));
                        }
                    } else {
                        $para[$a] = $b;
                    }
                }
            }
    
            return $para;
        }
    
        /**
         * 處理if標簽
         *
         * @access  public
         * @param   string $tag_args
         * @param   bool $elseif
         *
         * @return  string
         */
        private static function _compileIfTag($tag_args, $elseif = false)
        {
            preg_match_all('/\-?\d+[\.\d]+|\'[^\'|\s]*\'|"[^"|\s]*"|[\$\w\.]+|!==|===|==|!=|<>|<<|>>|<=|>=|&&|\|\||\(|\)|,|\!|\^|=|&|<|>|~|\||\%|\+|\-|\/|\*|\@|\S/', $tag_args, $match);
    
            $tokens = $match[0];
            // make sure we have balanced parenthesis
            $token_count = array_count_values($tokens);
            if (!empty($token_count['(']) && $token_count['('] != $token_count[')']) {
                // $this->_syntax_error('unbalanced parenthesis in if statement', E_USER_ERROR, __FILE__, __LINE__);
            }
    
            for ($i = 0, $count = count($tokens); $i < $count; $i++) {
                $token = &$tokens[$i];
                switch (strtolower($token)) {
                    case 'eq':
                        $token = '==';
                        break;
    
                    case 'ne':
                    case 'neq':
                        $token = '!=';
                        break;
    
                    case 'lt':
                        $token = '<';
                        break;
    
                    case 'le':
                    case 'lte':
                        $token = '<=';
                        break;
    
                    case 'gt':
                        $token = '>';
                        break;
    
                    case 'ge':
                    case 'gte':
                        $token = '>=';
                        break;
    
                    case 'and':
                        $token = '&&';
                        break;
    
                    case 'or':
                        $token = '||';
                        break;
    
                    case 'not':
                        $token = '!';
                        break;
    
                    case 'mod':
                        $token = '%';
                        break;
    
                    default:
                        if ($token[0] == '$') {
                            $token = self::get_val(substr($token, 1));
                        }
                        break;
                }
            }
    
            if ($elseif) {
                return '<?php elseif (' . implode(' ', $tokens) . '): ?>';
            } else {
                return '<?php if (' . implode(' ', $tokens) . '): ?>';
            }
        }
    
        /**
         * 處理foreach標簽
         *
         * @access  public
         * @param   string $tag_args
         *
         * @return  string
         */
        private static function _compileForeachStart($tag_args)
        {
            $attrs = self::getPara($tag_args, 0);
            $from = $attrs['from'];
            if (isset(self::$_var[$attrs['item']]) && !isset(self::$_patchstack[$attrs['item']])) {
                self::$_patchstack[$attrs['item']] = $attrs['item'] . '_' . str_replace(array(' ', '.'), '_', microtime());
                $attrs['item'] = self::$_patchstack[$attrs['item']];
            } else {
                self::$_patchstack[$attrs['item']] = $attrs['item'];
            }
            $item = self::get_val($attrs['item']);
    
            if (!empty($attrs['key'])) {
                $key = $attrs['key'];
                $key_part = self::get_val($key) . ' => ';
            } else {
                $key = null;
                $key_part = '';
                $attrs['key'] = '';
            }
    
            if (!empty($attrs['name'])) {
                $name = $attrs['name'];
            } else {
                $name = null;
            }
    
            $output = '<?php ';
            $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }; ";
            //$output .= "self::push_vars('".($attrs['key']?:'')."', '{$attrs['item']}');";
    
            if (!empty($name)) {
                $foreach_props = "self::\$_foreach['$name']";
                $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
                $output .= "if ({$foreach_props}['total'] > 0):\n";
                $output .= "    foreach (\$_from as $key_part$item):\n";
                $output .= "        {$foreach_props}['iteration']++;\n";
            } else {
                $output .= "if (count(\$_from)):\n";
                $output .= "    foreach (\$_from as $key_part$item):\n";
            }
            return $output . '?>';
        }
    
        /**
         * 彈出臨時數組的最后一個
         *
         * @return  void
         */
        private static function pop_vars()
        {
            $key = array_pop(self::$_temp_key);
            $val = array_pop(self::$_temp_val);
    
            if (!empty($key)) {
                eval($key);
            }
        }
    
        /**
         * 將 foreach 的 key, item 放入臨時數組
         * @param  mixed $key
         * @param  mixed $val
         * @return  void
         */
        /* private static function push_vars($key='', $val='')
         {
             if (!empty($key)) {
                 array_push(self::$_temp_key, "self::\$_var['$key']='" . self::$_var[$key] . "';");
             }
             if (!empty($val)) {
                 array_push(self::$_temp_val, "self::\$_var['$val']='" . self::$_var[$val] . "';");
             }
         }*/
    
    
        private static function html_options($arr)
        {
            $selected = $arr['selected'];
    
            if ($arr['options']) {
                $options = (array)$arr['options'];
            } elseif ($arr['output']) {
                if ($arr['values']) {
                    foreach ($arr['output'] as $key => $val) {
                        $options["{$arr[values][$key]}"] = $val;
                    }
                } else {
                    $options = array_values((array)$arr['output']);
                }
            }
            $out = '';
            if ($options) {
                foreach ($options as $key => $val) {
                    $out .= $key == $selected ? "<option value=\"$key\" selected>$val</option>" : "<option value=\"$key\">$val</option>";
                }
            }
    
            return $out;
        }
    
        private static function html_select_date($arr)
        {
            $pre = $arr['prefix'];
            if (isset($arr['time'])) {
                if (intval($arr['time']) > 10000) {
                    $arr['time'] = gmdate('Y-m-d', $arr['time'] + 8 * 3600);
                }
                $t = explode('-', $arr['time']);
                $year = strval($t[0]);
                $month = strval($t[1]);
                $day = strval($t[2]);
            }
            $now = gmdate('Y', self::$_nowtime);
            if (isset($arr['start_year'])) {
                if (abs($arr['start_year']) == $arr['start_year']) {
                    $startyear = $arr['start_year'];
                } else {
                    $startyear = $arr['start_year'] + $now;
                }
            } else {
                $startyear = $now - 3;
            }
    
            if (isset($arr['end_year'])) {
                if (strlen(abs($arr['end_year'])) == strlen($arr['end_year'])) {
                    $endyear = $arr['end_year'];
                } else {
                    $endyear = $arr['end_year'] + $now;
                }
            } else {
                $endyear = $now + 3;
            }
    
            $out = "<select name=\"{$pre}Year\">";
            for ($i = $startyear; $i <= $endyear; $i++) {
                $out .= $i == $year ? "<option value=\"$i\" selected>$i</option>" : "<option value=\"$i\">$i</option>";
            }
            if ($arr['display_months'] != 'false') {
                $out .= "</select>&nbsp;<select name=\"{$pre}Month\">";
                for ($i = 1; $i <= 12; $i++) {
                    $out .= $i == $month ? "<option value=\"$i\" selected>" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>";
                }
            }
            if ($arr['display_days'] != 'false') {
                $out .= "</select>&nbsp;<select name=\"{$pre}Day\">";
                for ($i = 1; $i <= 31; $i++) {
                    $out .= $i == $day ? "<option value=\"$i\" selected>" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>";
                }
            }
    
            return $out . '</select>';
        }
    
        private static function html_radios($arr)
        {
            $name = $arr['name'];
            $checked = $arr['checked'];
            $options = $arr['options'];
    
            $out = '';
            foreach ($options as $key => $val) {
                $out .= $key == $checked ? "<input type=\"radio\" name=\"$name\" value=\"$key\" checked>&nbsp;{$val}&nbsp;"
                    : "<input type=\"radio\" name=\"$name\" value=\"$key\">&nbsp;{$val}&nbsp;";
            }
    
            return $out;
        }
    
        private static function html_select_time($arr)
        {
            $pre = $arr['prefix'];
            if (isset($arr['time'])) {
                $arr['time'] = gmdate('H-i-s', $arr['time'] + 8 * 3600);
                $t = explode('-', $arr['time']);
                $hour = strval($t[0]);
                $minute = strval($t[1]);
                $second = strval($t[2]);
            }
            $out = '';
            if (!isset($arr['display_hours'])) {
                $out .= "<select name=\"{$pre}Hour\">";
                for ($i = 0; $i <= 23; $i++) {
                    $out .= $i == $hour ? "<option value=\"$i\" selected>" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>";
                }
    
                $out .= "</select>&nbsp;";
            }
            if (!isset($arr['display_minutes'])) {
                $out .= "<select name=\"{$pre}Minute\">";
                for ($i = 0; $i <= 59; $i++) {
                    $out .= $i == $minute ? "<option value=\"$i\" selected>" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>";
                }
    
                $out .= "</select>&nbsp;";
            }
            if (!isset($arr['display_seconds'])) {
                $out .= "<select name=\"{$pre}Second\">";
                for ($i = 0; $i <= 59; $i++) {
                    $out .= $i == $second ? "<option value=\"$i\" selected>" . str_pad($i, 2, '0', STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">$i</option>";
                }
    
                $out .= "</select>&nbsp;";
            }
    
            return $out;
        }
    
        private static function cycle($arr)
        {
            static $k, $old;
    
            $value = explode(',', $arr['values']);
            if ($old != $value) {
                $old = $value;
                $k = 0;
            } else {
                $k++;
                if (!isset($old[$k])) {
                    $k = 0;
                }
            }
    
            echo $old[$k];
        }
    
        private static function makeArray($arr)
        {
            $out = '';
            foreach ($arr as $key => $val) {
                if ($val{0} == '$') {
                    $out .= $out ? ",'$key'=>$val" : "array('$key'=>$val";
                } else {
                    $out .= $out ? ",'$key'=>'$val'" : "array('$key'=>'$val'";
                }
            }
    
            return $out . ')';
        }
    
        /**
         * 處理smarty開頭的預定義變量
         * @access  public
         * @param   array $indexes
         * @return  string
         */
        private static function _compileSmartyRef(&$indexes)
        {
            $_ref = $indexes[0];
    
            switch ($_ref) {
                case 'now':
                    $compiled_ref = 'time()';
                    break;
    
                case 'foreach':
                    array_shift($indexes);
                    $_var = $indexes[0];
                    $_propname = $indexes[1];
                    switch ($_propname) {
                        case 'index':
                            array_shift($indexes);
                            $compiled_ref = "(self::\$_foreach['$_var']['iteration'] - 1)";
                            break;
    
                        case 'first':
                            array_shift($indexes);
                            $compiled_ref = "(self::\$_foreach['$_var']['iteration'] <= 1)";
                            break;
    
                        case 'last':
                            array_shift($indexes);
                            $compiled_ref = "(self::\$_foreach['$_var']['iteration'] == self::\$_foreach['$_var']['total'])";
                            break;
    
                        case 'show':
                            array_shift($indexes);
                            $compiled_ref = "(self::\$_foreach['$_var']['total'] > 0)";
                            break;
    
                        default:
                            $compiled_ref = "self::\$_foreach['$_var']";
                            break;
                    }
                    break;
    
                case 'get':
                    $compiled_ref = '$_GET';
                    break;
    
                case 'post':
                    $compiled_ref = '$_POST';
                    break;
    
                case 'cookies':
                    $compiled_ref = '$_COOKIE';
                    break;
    
                case 'env':
                    $compiled_ref = '$_ENV';
                    break;
    
                case 'server':
                    $compiled_ref = '$_SERVER';
                    break;
    
                case 'request':
                    $compiled_ref = '$_REQUEST';
                    break;
    
                case 'session':
                    $compiled_ref = '$_SESSION';
                    break;
    
                default:
                    break;
            }
            array_shift($indexes);
    
            return $compiled_ref;
        }
    
        private static function smarty_insert_scripts($args)
        {
            static $scripts = array();
    
            $arr = explode(',', str_replace(' ', '', $args['files']));
    
            $str = '';
            foreach ($arr as $val) {
                if (in_array($val, $scripts) == false) {
                    $scripts[] = $val;
                    if ($val{0} == '.') {
                        $str .= '<script type="text/javascript" src="' . $val . '"></script>';
                    } else {
                        $str .= '<script type="text/javascript" src="js/' . $val . '"></script>';
                    }
                }
            }
    
            return $str;
        }
    
        private static function smarty_create_pages($params)
        {
            extract($params);
    
            if (empty($page)) {
                $page = 1;
            }
    
            if (!empty($count)) {
                $str = "<option value='1'>1</option>";
                $min = min($count - 1, $page + 3);
                for ($i = $page - 3; $i <= $min; $i++) {
                    if ($i < 2) {
                        continue;
                    }
                    $str .= "<option value='$i'";
                    $str .= $page == $i ? " selected='true'" : '';
                    $str .= ">$i</option>";
                }
                if ($count > 1) {
                    $str .= "<option value='$count'";
                    $str .= $page == $count ? " selected='true'" : '';
                    $str .= ">$count</option>";
                }
            } else {
                $str = '';
            }
    
            return $str;
        }
    
        private static function strTrim($str)
        {
            /* 處理'a=b c=d k = f '類字符串,返回數組 */
            while (strpos($str, '= ') != 0) {
                $str = str_replace('= ', '=', $str);
            }
            while (strpos($str, ' =') != 0) {
                $str = str_replace(' =', '=', $str);
            }
    
            return explode(' ', trim($str));
        }
    
    
        private static function _require($filename)
        {
            ob_start();
            ob_implicit_flush(0);
            include $filename;
            $content = ob_get_contents();
            ob_end_clean();
    
            return $content;
        }
    
        /**
         * 注冊變量
         * @param $tplVar
         * @param string $value
         */
        public static function assign($tplVar, $value = '')
        {
            if (is_array($tplVar)) {
                foreach ($tplVar as $key => $val) {
                    if ($key != '') {
                        self::$_var[$key] = $val;
                    }
                }
            } else {
                if ($tplVar != '') {
                    self::$_var[$tplVar] = $value;
                }
            }
        }
    
        /**
         * 驗證模板文件的存在
         * @param $viewFile
         * @return string
         */
        public static function checkTemplate($viewFile)
        {
            $viewFolder = PUBLIC_PATH . 'themes' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR;
            if (empty($viewFile)) {
                self::$templateFile = $viewFolder . CONTROLLER . DIRECTORY_SEPARATOR . ACTION . '.html';
            } else {
                $viewFileArr = explode(DIRECTORY_SEPARATOR, $viewFile);
                self::$templateFile = $viewFolder . $viewFileArr[0] . DIRECTORY_SEPARATOR . $viewFileArr[1];
            }
            if (file_exists(self::$templateFile)) {
                return self::$templateFile;
            } else {
                //拋出模板文件不存在異常
                echo "template file does not exist";
                exit();
            }
        }
    
    
    }
    

    msql類

    system/database/DB.php

    <?php
    
    namespace database;
    
    use core\Env;
    
    class DB
    {
        public static $__pdo = null;        // 默認PDO對象
        public static $__is_mysql = null;        // 默認是否mysql數據庫
        public static $__dsn = "mysql:host=%s;port=%s;dbname=%s;charset=%s;"; // DSN
        public static $__host = "";    // 默認主機
        public static $__port = "";    // 端口
        public static $__username = "";        // 默認賬戶
        public static $__password = "";    // 默認密碼
        public static $__dbname = "";        // 默認數據庫名稱
        public static $__charset = "";        // 默認字符集
        public static $__prefix = "";            // 默認表前綴
        protected $_pdo = null;        // PDO對象
        protected $_is_mysql = null;        // 默認是否mysql數據庫
        protected static $_prefix = null;        // 表前綴
        protected static $_table = null;        // 表名
        protected static $_alias = null;        // 表別名
        protected static $_fulltable = null;        // 表全名
        protected static $_instance = false;
        protected $_pk = null;        // 主鍵
        private $_keywords = array();        // keywords
        private $_columns = array();        // columns
        private $_joins = array();        // joins
        private $_wheres = array();        // where
        private $_wheres_params = array();        // where params
        private $_groups = array();        // group
        private $_havings = array();        // having
        private $_havings_params = array();        // having params
        private $_orders = array();        // order
        private $_limit = null;        // limit
        private $_offset = null;        // offset
        private $_for_update = "";            // read lock
        private $_lock_in_share_mode = "";            // write lock
        private $_count_wheres = array();        // count where
        private $_count_wheres_params = array();        // count where params
        private $_exp = array('eq' => '=', 'ne' => '<>', 'gt' => '>', 'ge' => '>=', 'lt' => '<', 'le' => '<=',
            'not like' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN',
            'not between' => 'NOT BETWEEN',);
        private $_incDbLinkNums = 0;
        public $_sql = "";            // sql
        public $_params = array();        // params
    
    
        public static function getInstance()
        {
            if (self::$_instance == false) {
                self::$_instance = new self();
            }
            return self::$_instance;
        }
    
        // 獲取參數類型
        private static function type($param)
        {
            static $types = array(
                "boolean" => \PDO::PARAM_BOOL,
                "NULL" => \PDO::PARAM_NULL,
                "double" => \PDO::PARAM_INT,
                "integer" => \PDO::PARAM_INT,
                "string" => \PDO::PARAM_STR,
            );
            $type = gettype($param);
            return array_key_exists($type, $types) ? $types[$type] : \PDO::PARAM_STR;
        }
    
        public function __construct()
        {
            self::$__host = Env::get('DB_HOST') ? Env::get('DB_HOST') : '127.0.0.1';
            self::$__port = Env::get('DB_PORT') ? Env::get('DB_PORT') : '3306';
            self::$__username = Env::get('DB_USER') ? Env::get('DB_USER') : 'root';
            self::$__password = Env::get('DB_PWD') ? Env::get('DB_PWD') : 'root';
            self::$__dbname = Env::get('DB_NAME') ? Env::get('DB_NAME') : 'test';
            self::$__charset = Env::get('DB_CHATSET') ? Env::get('DB_CHATSET') : 'utf8';
        }
    
        // 設置表前綴
        public function prefix($prefix = "")
        {
            self::$_prefix = $prefix;
            self::$_fulltable = self::$_prefix . self::$_table;
            return $this;
        }
    
        // 設置表名
        public static function table($table = "")
        {
            if (strpos($table, " as ")) {
                list($table, $alias) = explode(" as ", $table);
                self::$_alias = $alias;
            }
            self::$_table = $table;
            self::$_fulltable = self::$_prefix . self::$_table;
            return self::getInstance();
        }
    
        // 設置表別名
        public function alias($alias = "")
        {
            self::$_alias = $alias;
            return $this;
        }
    
        // 設置主鍵名稱
        public function pk($pk = "id")
        {
            $this->_pk = $pk;
            return $this;
        }
    
        // 設置MySQL關鍵字
        public function keyword($keyword)
        {
            if ($this->is_mysql()) {
                $this->_keywords[] = $keyword;
            }
            return $this;
        }
    
        // 設置SQL_CALC_FOUND_ROWS關鍵字
        public function calcFoundRows()
        {
            return $this->keyword("SQL_CALC_FOUND_ROWS");
        }
    
        // column返回的列
        public function select($column)
        {
            $this->_columns[] = $column;
            return $this;
        }
    
        // leftjoin連表查詢
        public function leftjoin($join, $cond)
        {
    
            list($table, $alias) = explode(" as ", $join);
            $prefix = strpos($table, "`") === 0 ? "" : self::$__prefix;
            if (empty($alias)) {
                $this->_joins[] = sprintf("`%s%s` ON `%s`", $prefix, $table, $cond);
            } else {
                $this->_joins[] = sprintf("`%s%s` AS `%s` ON %s", $prefix, $table, $alias, $cond);
            }
            return $this;
        }
    
        // where查詢條件
        public function where($where)
        {
            if (is_array($where)) {
                $this->arrayWhere($where);
            } else {
                $args = array_slice(func_get_args(), 1);
                $this->stringWhere($where, $args);
            }
            return $this;
        }
    
        private function stringWhere($where, $args)
        {
            $ws = explode("?", $where);
            $where = array_shift($ws);
            $params = array();
            foreach ($ws as $i => $w) {
                if (!empty($args) && is_array($args[$i])) {
                    $where .= "?" . str_repeat(",?", count($args[$i]) - 1) . $w;
                    $params = array_merge($params, $args[$i]);
                } else {
                    $where .= "?" . $w;
                    !empty($args) && $params[] = $args[$i];
                }
            }
            $this->_wheres[] = $where;
            $this->_wheres_params = array_merge($this->_wheres_params, $params);
        }
    
        /**
         * where數組分析
         * @param $where
         */
        private function arrayWhere($where)
        {
            $whereStr = '';
            $operate = ' and ';
            foreach ($where as $key => $val) {
                $whereStr .= $this->parseWhereItem($key, $val);
                $whereStr .= $operate;
            }
            $whereStr = substr($whereStr, 0, -strlen($operate));
            $this->stringWhere($whereStr, '');
        }
    
        // where子單元分析
        private function parseWhereItem($key, $val)
        {
            $whereStr = '';
            if (is_array($val)) {
                if (is_string($val[0])) {
                    $exp = strtolower($val[0]);
                    if (preg_match('/^(eq|ne|gt|ge|lt|le)$/', $exp)) { // 比較運算
                        $whereStr .= $key . ' ' . $this->_exp[$exp] . ' ?';
                        $this->_wheres_params[] = $val[1];
                    } elseif (preg_match('/^(not like|like)$/', $exp)) { // 模糊查找
                        if (is_array($val[1])) {
                            $likeLogic = isset($val[2]) ? strtolower($val[2]) : 'OR';
                            if (in_array($likeLogic, array('AND', 'OR', 'XOR'))) {
                                $like = array();
                                foreach ($val[1] as $item) {
                                    $like[] = $key . ' ' . $this->_exp[$exp] . ' ?';
                                    $this->_wheres_params[] = $item;
                                }
                                $whereStr .= '(' . implode(' ' . $likeLogic . ' ', $like) . ')';
                            }
                        } else {
                            $whereStr .= $key . ' ' . $this->_exp[$exp] . ' ?';
                            $this->_wheres_params[] = $val[1];
                        }
                    } elseif (preg_match('/^(not in|in)$/', $exp)) { // IN 運算
                        if (is_string($val[1])) {
                            $val[1] = explode(',', $val[1]);
                        }
                        $zone = '';
                        foreach ($val[1] as $valInItem) {
                            $zone .= "?,";
                            $this->_wheres_params[] = $valInItem;
                        }
                        $zone = rtrim($zone, ",");
                        $whereStr .= $key . ' ' . $this->_exp[$exp] . " ({$zone})";
                    } elseif (preg_match('/^(not between|between)$/', $exp)) { // BETWEEN運算
                        $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1];
                        $whereStr .= $key . ' ' . $this->_exp[$exp] . ' ? AND ?';
                        $this->_wheres_params[] = $data[0];
                        $this->_wheres_params[] = $data[1];
                    } else {
                        throw new Exception('not_support_expressions_' . $val[0] . '=>' . $val[1]);
                    }
                } else {
                    $count = count($val);
                    $rule = isset($val[$count - 1]) ? (is_array($val[$count - 1]) ? strtolower($val[$count - 1][0]) : strtolower($val[$count - 1])) : '';
                    if (in_array($rule, array('AND', 'OR', 'XOR'))) {
                        $count = $count - 1;
                    } else {
                        $rule = 'AND';
                    }
                    for ($i = 0; $i < $count; $i++) {
                        $whereStr .= $this->parseWhereItem($key, $val[$i]) . ' ' . $rule . ' ';
                    }
                    $whereStr = '( ' . substr($whereStr, 0, -4) . ' )';
                }
            } else {
                $whereStr .= $key . ' = ?';
                $this->_wheres_params[] = $val;
            }
            return $whereStr;
        }
    
        // group分組
        public function group($group)
        {
            $this->_groups[] = $group;
            return $this;
        }
    
        // having過濾條件
        public function having($having)
        {
            $args = array_slice(func_get_args(), 1);
            $ws = explode("?", $having);
            $having = array_shift($ws);
            $params = array();
            foreach ($ws as $i => $w) {
                if (is_array($args[$i])) {
                    $having .= "?" . str_repeat(",?", count($args[$i]) - 1) . $w;
                    $params = array_merge($params, $args[$i]);
                } else {
                    $having .= "?" . $w;
                    $params[] = $args[$i];
                }
            }
            $this->_havings[] = $having;
            $this->_havings_params = array_merge($this->_havings_params, $params);
            return $this;
        }
    
        // order排序
        public function order($order)
        {
            $this->_orders[] = $order;
            return $this;
        }
    
        // limit數據
        public function limit($limit)
        {
            $this->_limit = intval($limit);
            return $this;
        }
    
        // offset偏移
        public function offset($offset)
        {
            $this->_offset = intval($offset);
            return $this;
        }
    
        // 獨占鎖,不可讀不可寫
        public function forUpdate()
        {
            $this->_for_update = " FOR UPDATE";
            return $this;
        }
    
        // 共享鎖,可讀不可寫
        public function lockInShareMode()
        {
            $this->_lock_in_share_mode = " LOCK IN SHARE MODE";
            return $this;
        }
    
        // 設置和獲取PDO對象
        public function pdo($pdo = null)
        {
            if ($pdo !== null && is_a($pdo, "\\PDO")) {
                $this->_pdo = $pdo;
                $this->_is_mysql = $this->_pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === "mysql";
                return $this;
            }
            if (isset($this->_pdo)) {
                return $this->_pdo;
            }
            if (isset(self::$__pdo)) {
                return self::$__pdo;
            }
            $dsn = sprintf(self::$__dsn, self::$__host, self::$__port, self::$__dbname, self::$__charset);
            $options = array(
                \PDO::ATTR_PERSISTENT => true,
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
                \PDO::ATTR_STRINGIFY_FETCHES => false,
                \PDO::ATTR_EMULATE_PREPARES => false,
            );
            self::$__pdo = new \PDO($dsn, self::$__username, self::$__password, $options);
            if (empty(self::$__pdo) && $this->_incDbLinkNums <= 2) {
                $this->_incDbLinkNums++;
                $this->pdo();
            }
            self::$__is_mysql = self::$__pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === "mysql";
            return self::$__pdo;
        }
    
        // 獲取當前PDO是否是mysql數據庫
        public function is_mysql($is_mysql = null)
        {
            if ($is_mysql === null) {
                return $this->_is_mysql !== null ? $this->_is_mysql : (self::$__is_mysql !== null ? self::$__is_mysql : false);
            }
            $this->_is_mysql = $is_mysql;
            return $this;
        }
    
        // 事務開始
        public function begin()
        {
            return $this->pdo()->beginTransaction();
        }
    
        // 事務提交
        public function commit()
        {
            return $this->pdo()->commit();
        }
    
        // 事務回滾
        public function rollBack()
        {
            return $this->pdo()->rollBack();
        }
    
        // sql查詢
        public static function query($sql)
        {
            $params = array_slice(func_get_args(), 1);
            return self::getInstance()->vquery($sql, $params);
        }
    
        // sql查詢
        public function vquery($sql, $params = array())
        {
            /*if (strpos($sql, "'") !== false || strpos($sql, '"') !== false) {
                throw new \LogicException("query is not right");
            }*/
            $this->_sql = $this->doTheSql($params, $sql);
    
            $this->_params = $params;
            $stmt = $this->pdo()->prepare($sql);
            foreach ($params as $i => $param) {
                $stmt->bindValue($i + 1, $param, self::type($param));
            }
            $stmt->executeResult = $stmt->execute();
            $this->reset();
            return $stmt;
        }
    
        // 組裝查詢數據
        private function assembleData($columns = null, $isGetSql = false)
        {
            if (!empty($columns)) {
                $this->_columns[] = $columns;
            }
            $keywords = empty($this->_keywords) ? "" : " " . implode(" ", $this->_keywords);
            $columns = empty($this->_columns) ? "*" : implode(", ", $this->_columns);
            $table = self::$_fulltable . (!empty(self::$_alias) && !empty($this->_joins) ? "` AS `" . self::$_alias : "");
            $joins = empty($this->_joins) ? "" : " LEFT JOIN " . implode(" LEFT JOIN ", $this->_joins);
            $wheres = empty($this->_wheres) ? "" : " WHERE " . implode(" AND ", $this->_wheres);
            $groups = empty($this->_groups) ? "" : " GROUP BY " . implode(", ", $this->_groups);
            $havings = empty($this->_havings) ? "" : " HAVING " . implode(" AND ", $this->_havings);
            $orders = empty($this->_orders) ? "" : " ORDER BY " . implode(", ", $this->_orders);
            $limit = !isset($this->_limit) ? "" : " LIMIT ?";
            $offset = !isset($this->_offset) ? "" : " OFFSET ?";
            $forUpdate = $this->_for_update;
            $lockInShareMode = $this->_lock_in_share_mode;
            $sql = sprintf("SELECT%s %s FROM `%s`%s%s%s%s%s%s%s%s%s", $keywords, $columns, $table, $joins, $wheres, $groups, $havings, $orders, $limit, $offset, $forUpdate, $lockInShareMode);
            $params = array_merge($this->_wheres_params, $this->_havings_params);
            if (isset($this->_limit)) {
                $params[] = $this->_limit;
            }
            if (isset($this->_offset)) {
                $params[] = $this->_offset;
            }
            $this->_count_wheres = $this->_wheres;
            $this->_count_wheres_params = $this->_wheres_params;
    
            if ($isGetSql) {
                $this->_sql = $this->doTheSql($params, $sql);
                return $this->_sql;
            }
    
            return $this->vquery($sql, $params);
        }
    
        /**
         * 拼接sql
         * @param $params
         * @param $sql
         * @return mixed
         */
        private function doTheSql($params, $sql)
        {
            foreach ($params as $paramsItem) {
                is_string($paramsItem) && $paramsItem = '"' . $paramsItem . '"';
                $sql = substr_replace($sql, $paramsItem, strpos($sql, "?"), strlen("?"));
            }
            return $sql;
        }
    
        public function fetchAll()
        {
            return $this->assembleData()->fetchAll();
        }
    
        public function fetch()
        {
            return $this->assembleData()->fetch();
        }
    
        // 添加數據
        public function insert(array $data)
        {
            $cols = array();
            $sets = array();
            $params = array();
            foreach ($data as $col => $val) {
                $cols[] = sprintf("`%s`", $col);
                $sets[] = sprintf("`%s` = ?", $col);
                $params[] = $val;
            }
            if ($this->is_mysql()) {
                $sql = sprintf("INSERT INTO `%s` SET %s", self::$_fulltable, implode(", ", $sets));
            } else {
                $sql = sprintf("INSERT INTO `%s` (%s) VALUES (?%s)", self::$_fulltable, implode(", ", $cols), str_repeat(", ?", count($cols) - 1));
            }
            $affectRow = $this->vquery($sql, $params)->rowCount();
            if ($affectRow) {
                return $this->lastInsertId();
            }
            return false;
        }
    
        // 獲取自增ID
        public function lastInsertId()
        {
            return $this->pdo()->lastInsertId();
        }
    
        // 獲取符合條件的行數
        public function count()
        {
            if ($this->is_mysql()) {
                return $this->vquery("SELECT FOUND_ROWS()")->fetchColumn();
            } else {
                $wheres = empty($this->_count_wheres) ? "" : " WHERE " . implode(" AND ", $this->_count_wheres);
                $sql = sprintf("SELECT count(*) FROM `%s`%s", self::$_fulltable, $wheres);
                return $this->vquery($sql, $this->_count_wheres_params)->fetchColumn();
            }
        }
    
        // 批量插入數據
        public function batchInsert(array $columns, array &$rows, $batch = 100)
        {
            $column = implode("`,`", $columns);
            $value = ",(?" . str_repeat(",?", count($columns) - 1) . ")";
            $params = array();
            $len = count($rows);
            for ($i = 0; $i < $len; $i++) {
                $params = array_merge($params, $rows[$i]);
                if (($i + 1) % $batch == 0) {
                    $sql = sprintf("INSERT INTO `%s` (`%s`) VALUES %s%s", self::$_fulltable, $column, substr($value, 1), str_repeat($value, $batch - 1));
                    $this->vquery($sql, $params);
                    $params = array();
                }
            }
            if ($len % $batch > 0) {
                $sql = sprintf("INSERT INTO `%s` (`%s`) VALUES %s%s", self::$_fulltable, $column, substr($value, 1), str_repeat($value, $len % $batch - 1));
                $this->vquery($sql, $params);
            }
            return $this;
        }
    
        // 更新數據
        public function update(array $data)
        {
            if (empty($this->_wheres)) {
                throw new \LogicException("where is empty!");
            }
            $sets = array();
            $params = array();
            foreach ($data as $col => $val) {
                $sets[] = sprintf("`%s` = ?", $col);
                $params[] = $val;
            }
            $wheres = " WHERE " . implode(" AND ", $this->_wheres);
            $orders = empty($this->_orders) ? "" : " ORDER BY " . implode(", ", $this->_orders);
            $limit = !isset($this->_limit) ? "" : " LIMIT ?";
            $sql = sprintf("UPDATE `%s` SET %s%s%s%s", self::$_fulltable, implode(", ", $sets), $wheres, $orders, $limit);
            $params = array_merge($params, $this->_wheres_params);
            if (isset($this->_limit)) {
                $params[] = $this->_limit;
            }
            return $this->vquery($sql, $params)->rowCount();
        }
    
        // 替換數據
        public function replace(array $data)
        {
            $sets = array();
            $params = array();
            foreach ($data as $col => $val) {
                $sets[] = sprintf("`%s` = ?", $col);
                $params[] = $val;
            }
            $sql = sprintf("REPLACE INTO `%s` SET %s", self::$_fulltable, implode(", ", $sets));
            return $this->vquery($sql, $params);
        }
    
        // 刪除數據
        public function delete()
        {
            if (empty($this->_wheres)) {
                throw new \LogicException("WHERE is empty!");
            }
            $wheres = " WHERE " . implode(" AND ", $this->_wheres);
            $orders = empty($this->_orders) ? "" : " ORDER BY " . implode(", ", $this->_orders);
            $limit = !isset($this->_limit) ? "" : " LIMIT ?";
            $sql = sprintf("DELETE FROM `%s`%s%s%s", self::$_fulltable, $wheres, $orders, $limit);
            $params = $this->_wheres_params;
            if (isset($this->_limit)) {
                $params[] = $this->_limit;
            }
            return $this->vquery($sql, $params)->rowCount();
        }
    
        // 重置所有
        public function reset()
        {
            $this->_debug = false;
            $this->_keywords = array();
            $this->_columns = array();
            $this->_joins = array();
            $this->_wheres = array();
            $this->_wheres_params = array();
            $this->_groups = array();
            $this->_havings = array();
            $this->_havings_params = array();
            $this->_orders = array();
            $this->_limit = null;
            $this->_offset = null;
            $this->_for_update = "";
            $this->_lock_in_share_mode = "";
            return $this;
        }
    
        // page分頁
        public function page($page = null, $pagesize = 15)
        {
            $page = intval(isset($page) ? $page : (isset($_GET["p"]) ? $_GET["p"] : 1));
            $pagesize = intval($pagesize);
            $this->_limit = $pagesize;
            $this->_offset = ($page - 1) * $pagesize;
            return $this;
        }
    
        // pagination分頁
        public function pagination($pagesize = 15)
        {
            $args = array_slice(func_get_args(), 1);
            $pagination = new Pagination($this->count(), null, $pagesize);
            if (!empty($format)) {
                call_user_func_array(array($pagination, "setStatic"), $args);
            }
            return $pagination->show();
        }
    
        // 將選中行的指定字段加一
        public function plus($col, $val = 1)
        {
            $args = array_slice(func_get_args(), 2);
            $sets = array(sprintf("`%s` = `%s` + ?", $col, $col));
            $vals = array($val);
            while (count($args) > 1) {
                $col = array_shift($args);
                $val = array_shift($args);
                $sets[] = sprintf("`%s` = `%s` + ?", $col, $col);
                $vals[] = $val;
            }
            if (empty($this->_wheres)) {
                throw new \LogicException("WHERE is empty!");
            }
            $wheres = " WHERE " . implode(" AND ", $this->_wheres);
            $sql = sprintf("UPDATE `%s` SET %s%s", self::$_fulltable, implode(", ", $sets), $wheres);
            $params = array_merge($vals, $this->_wheres_params);
            $this->vquery($sql, $params);
            return $this;
        }
    
        // 將選中行的指定字段加一
        public function incr($col, $val = 1)
        {
            if (empty($this->_wheres)) {
                throw new \LogicException("WHERE is empty!");
            }
            $wheres = " WHERE " . implode(" AND ", $this->_wheres);
            $sql = sprintf("UPDATE `%s` SET `%s` = last_insert_id(`%s` + ?)%s", self::$_fulltable, $col, $col, $wheres);
            $params = array_merge(array($val), $this->_wheres_params);
            $this->vquery($sql, $params);
            return $this->pdo()->lastInsertId();
        }
    
        // 根據主鍵查找行
        public function find($id)
        {
            return $this->where(sprintf("`%s` = ?", $this->_pk), $id)->assembleData()->fetch();
        }
    
        // 添加數據
        public function add(array $data)
        {
            return $this->insert($data);
        }
    
        // 編輯數據
        public function edit(array $data)
        {
            if (!array_key_exists($this->_pk, $data)) {
                throw new \LogicException("\$data must contains column {$this->_pk}!");
            }
            $pk_val = $data[$this->_pk];
            unset($data[$this->_pk]);
            return $this->where(sprintf("`%s` = ?", $this->_pk), $pk_val)->update($data);
        }
    
        // 添加數據
        public function del($id)
        {
            return $this->where(sprintf("`%s` = ?", $this->_pk), $id)->delete();
        }
    
        // 保存數據,自動判斷是新增還是更新
        public function save(array $data)
        {
            if (array_key_exists($this->_pk, $data)) {
                return $this->edit($data);
            } else {
                return $this->add($data);
            }
        }
    
        // 獲取外鍵數據
        public function foreignKey(array $rows, $foreign_key, $columns = "*")
        {
            $ids = array_column($rows, $foreign_key);
            if (empty($ids)) {
                return new \PDOStatement();
            }
            $ids = array_unique($ids);
            return $this->where(sprintf("`%s` IN (?)", $this->_pk), $ids)->assembleData($columns);
        }
    
        //獲取sql語句
        public function getSql()
        {
            return $this->assembleData('', true);
        }
    }
    
    

    應用

    數據庫部署

    在 SQL 中新建一個test 數據庫,增加一個users 表

    DROP TABLE IF EXISTS `users`;
    CREATE TABLE `users`  (
      `user_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用戶id',
      `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '名稱',
      PRIMARY KEY (`user_id`) USING BTREE,
      UNIQUE INDEX `name`(`name`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶表' ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of users
    -- ----------------------------
    INSERT INTO `users` VALUES (1, 'gsj1');
    INSERT INTO `users` VALUES (2, 'gsj2');
    INSERT INTO `users` VALUES (3, 'gsj3');
    

    模型部署

    app/model/IndexModel.php

    <?php
    
    namespace model;
    
    use core\Model;
    use database\DB;
    
    class IndexModel extends Model
    {
    
        public function doSomething()
        {
            $sq = "Welcome to doopsPHP!";
            return $sq;
        }
    
        public function getUsersList()
        {
            //sql查詢
            /*$sql = "select user_id,name from users where user_id=1";
            $res = DB::query($sql)->fetch(); //單條fetch(),多條fetchAll()*/
    
            //插入數據
            /*$data=['name'=>'gsj2019'];
            DB::table('users')->insert($data); //返回主鍵id*/
    
            //批量插入
            /*$fields = ['name'];
            for ($i=1; $i<=10; $i++) {
                $rowsArr[] = array("gsj_".mt_rand(100, 500));
            }
            DB::table('users')->batchInsert($fields, $rowsArr);*/
    
    
            // 刪除數據
            //$res=DB::table('users')->where(['user_id' => 4])->delete();//返回影響條數
    
            //更新數據
            /*$data=['name'=>'gsj2020'];
            $res=DB::table('users')->where(['user_id'=>4])->update($data); //返回影響條數*/
    
    
            //獲取sql語句 getSql()
            //$res=DB::table('users')->select("user_id,name")->getSql();
    
            //全部查詢
            //DB::table('users')->select("user_id,name")->fetchAll();
    
            //查詢單行
            //DB::table('users')->select("user_id,name")->where('user_id = ?', 1)->fetch();
    
            //where條件查詢
            $where = [
                //'name'=>'gsj',
                //'user_id'=>array('le', 3),
                'user_id' => array('in', array(1, 2, 3)),
                //'name'=>array('like', '%gsj%'),
                //'user_id'=>array( 'between', "1,3" ),
            ];
            $res=DB::table('users')->where($where)->fetchAll();
    
            //注:ne不等于、gt大于、ge大于等于、lt小于、le小于等于、like像、not like不像
            //in在范圍、not in不在范圍、between在…中間、not between不在…中間
            //DB::table('users')->where('user_id = ? and name=?', 1,"gsj")->fetch();
    
            //左連接
            /*$res=DB::table('users as u')->select("u.user_id,u.name,ui.job")->where(['u.user_id'=>1])
                ->leftjoin('users_info as ui','u.user_id=ui.user_id')->fetch();*/
    
            return $res;
        }
    }
    

    控制器部署

    app/controller/Index.php

    <?php
    
    namespace Controller;
    
    use core\Controller;
    use model\IndexModel;
    
    
    class Index extends Controller
    {
    
        private $indexModel;
    
        public function __construct()
        {
            $this->indexModel = new IndexModel();
        }
    
        /**
         *
         */
        public function index()
        {
            $result = $this->indexModel->doSomething();
            $useArr = $this->indexModel->getUsersList();
            $data = [
                'sq' => $result,
                'users' => $useArr,
            ];
            $this->render('index/index.html', $data);
        }
    
        public function test()
        {
            $res = $this->indexModel->getUsersList();
            echo "<pre>";
            print_r($res);
            die();
        }
    
        public function shop()
        {
            $arr = $_GET;
            echo "<pre>";
            print_r($arr);
            die();
        }
    }
    

    視圖部署

    public/themes/default/index/index.html

    <!DOCTYPE HTML>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>{$sq}</title>
        <style type="text/css">
            *{margin:0;padding:0}
            body{background:#f5f6f7}
            #myborder{background:#fff;width:600px;height:320px;position:fixed;left:50%;top:50%;z-index:11;margin:-200px 0 0 -350px;border-radius:5px}
            #myTitle{height:50px;text-align:center;padding:30px;font-size:40px}
            #myContent{height:50px;text-align:center;padding:30px;font-size:28px;color:#fff;background:#b9b9b9}
            #myFoot{height:50px;text-align:center;padding:30px;font-size:22px}
        </style>
    </head>
    <body>
    <div id="myborder">
        <div id="myTitle">
            Congratulation
        </div>
        <div id="myContent">
            {$sq}
            <div>
                {if $users}
                    {foreach from=$users key=users_key item=users_item}
                        {$users_key} => {$users_item.name}
                    {/foreach}
                {/if}
            </div>
        </div>
        <div id="myFoot">
            精彩從現在開始
        </div>
    
    </div>
    </body>
    </html>
    

    應用測試

    訪問rul
    顯示
    在這里插入圖片描述

    版權聲明:本文為gusijin原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/gusijin/article/details/104947607

    智能推薦

    ionic框架入門

      1.Chocolatey Chocolatey是一個Windows上的包管理器,類似于linux上的yum和apt-get。 你可以在其官方網站上查看具體的使用說明。一般的安裝步驟應該是下面這樣: 一般來說,使用Chocolatey來安裝軟件的時候,需要以管理員的身份來運行命令提示符窗口。譯注:chocolatey的網站可能在國內訪問困難,導致上述安裝命令無法正常完成。請使用穩定的翻...

    Mybatis框架入門

    Mybatis官網:http://www.mybatis.org/mybatis-3/ Mybatis的介紹 Mybatis是一個操作數據庫的框架。最開始叫做ibatis,從apache基金會脫離,加入googleCode正式更名為MyBatis。最終現在mybatis的代碼托管在github mybatis架構介紹 1、 mybatis配置SqlMapConfig.xml,此文件作為mybati...

    Spring框架入門

    文章目錄 Java Spring框架是什么?它有哪些好處? Spring體系結構詳解 Spring目錄結構和基礎JAR包介紹 Spring IoC容器:BeanFactory和ApplicationContext 第一個Spring程序 Spring DI(依賴注入)的實現方式:屬性注入和構造注入 Spring Bean的配置及常用屬性 Spring實例化Bean的三種方法 Spring中Bean...

    scrapy框架入門

    scrapy框架入門 一、Scrapy框架介紹 1.框架簡介 Scrapy是純Python開發的一個高效,結構化的網頁抓取框架 Scrapy使用了Twisted 異步網絡庫來處理網絡通訊 Scrapy是為了爬取網站數據,提取結構性數據而編寫的應用框架 Scrapy用途廣泛,可以用于數據挖掘、監測和自動化測試 2.模塊安裝 scrapy支持Python2.7和python3.4以上版本 python...

    Spring框架入門

    Spring 框架概述  1.1. 什么是Spring  Spring是分層的JavaSE/EE full-stack(一站式) 輕量級開源框架  分層: 來自JavaEE體系結構 (客戶端層、 web層、業務層、持久層 )  服務器端三層結構 (web層、業務層、持久層)  Servlet + JSP —- web層技術 &mdash...

    猜你喜歡

    Spring《框架入門》

    Spring用的jar包之一部分 配置簡單的日志文件需要的jar包 Spring基本的xml配置文件 現在開始建java項目 新建Dao類,User類方便測試 測試類 其中ClassPathXmlApplicationContext通過將Spring的xml配置文件全名傳入構造方法中,返回一個實現ApplicationContext接口的對象,這時候配置文件中的信息已經全部掃描進去,生成的對象方法...

    scrapy框架入門

    scrapy框架 Scrapy是用純Python實現一個為了爬取網站數據、提取結構性數據而編寫的應用框架,用途非常廣泛。 框架的力量,用戶只需要定制開發幾個模塊就可以輕松的實現一個爬蟲,用來抓取網頁內容以及各種圖片,非常之方便。 Scrapy 使用了 Twisted’tw?st?d異步網絡框架來處理網絡通訊,可以加快我們的下載速度,不用自己去實現異步框架,并且包含了各種中間件接口,可以...

    express框架入門

    本篇講述express框架入門 安裝express-generator(可以快速創建一個應用框架):npm install express-generator -g 創建一個express項目:在命令行輸入express --view=(模板名稱) 項目名稱 我這里使用的是ejs模板,port是我的項目名稱,其支持的模板有:ejs|hbs|hjs|jade|pug|twig|vash,根據自己的需...

    Hibernate框架入門

    導讀 本文主要介紹hibernate的入門,主要包括以下內容:hibernate介紹、hibernate環境搭建、hibernate簡單測試、測試涉及的api詳解。 一、hibernate介紹 JDBC是Java操作數據庫的工具,我們可以使用jdbc來書寫并執行sql語句來操作數據庫,對于普通的業務,jdbc工具是完全可以勝任的,但但當任務復雜,特別是數據庫中表格很多的時候,jdbc就會顯得力不從...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    精品国产乱码久久久久久蜜桃不卡