[
  {
    "path": ".gitignore",
    "content": ".idea\n/logs"
  },
  {
    "path": "README.md",
    "content": "# ![运营商][1] PHP-ES\n[![Stars](https://img.shields.io/github/stars/echosong/es.svg)](https://github.com/es/echosong/stargazers)\n[![Forks](https://img.shields.io/github/forks/echosong/es.svg)](https://github.com/es/echosong/network)\n\n## 框架简介\nPHP-ES 是一款 极简、灵活、 高性能、扩建性强、上手快php 框架; 以“快速开发、轻松上手、高速执行”为理念，助你成为web开发的能手 ！\n\n### 开发缘由\n\n与其说开发此框架，更准确说法应该是一次代码的整理，本人在接触将近10年的php开发过程中，陆续也接触了一些优秀的框架。不仅仅php\n有asp.net mvc、php laravel、php yii、python web.py、python django、golang beego 等等 框架各自有各自的优势，但是使用场景\n和性能方面各有所长，在2015年给公司同事分享mvc核心思想的时候， 我在想既然用了这些框架那是不是自己整理出一些核心的、或者说是开发过程中最需要的部分，\n来写自己的这么一个极简型框架，如此便有了 ES。\n\n## 框架结构\n\n整个框架核心五个文件，所有文件加起来放在一起总行数不超过400 行，总大小 18k。\n\n```\n|--src //受保护代码文件夹\n  |--core\n    |--es.php //启动文件\n    |- helper.php //实现流程的核心方法类\n    |--controller.php //控制器文件\n    |--model.php //模型文件\n    |--view.php //视图引擎\n  |--controller //控制器业务文件\n  |--view //视图文件\n  |--model //模型一般小型业务可以省略，数据操作直接放到controller \n  |--config.php //全局配置文件，业务相关的配置也可以放这里，或者自己建立一个独立的配置文件index.php 文件引用\n|--res //静态资源\n|--logs // 日志记录路径 可以省如果有请保证有写入权限\n|--index.php //入口文件\n\n```\n\n\n## 安装\n\n### 下载\n    git clone https://github.com/Echosong/es（web建立到当前文件夹）\n\n### 各种web 服务器配置重定向\n\n.hitaccess(Apache):\n\n    RewriteEngine On\n    RewriteBase /\n    \n    # Allow any files or directories that exist to be displayed directly\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteCond %{REQUEST_FILENAME} !-d\n    \n    RewriteRule ^(.*)$ index.php/$1 [QSA,L]\n \n.htaccess(Nginx):\n    \n    rewrite ^/(.*)/$ /$1 redirect;\n    \n    if (!-e $request_filename){\n        rewrite ^(.*)$ /index.php break;\n    }\n\n### 配置域名访问比如： http://es.dev/ (hosts 修改)\n\n(ES 和 Laravel 性能比较 http://esassets.oss-cn-shanghai.aliyuncs.com/x.png )\n\n## 具体实现功能\n\n### 配置文件\n\n#### 配置路由规则\n\nES 没有像些重型框架单独有 Route 配置， ES的想法很简单，主要分为 模块[m]，控制器[c]，动作[a] 来路由\n\n```php\n 'rewrite' => array(\n        //设置模块 碰到 http://{host}/admin/ 认为进入了后台模块 数组 0 标识默认 m\n       'm'=>['web','admin','app','api'], \n       'c'=>'main', //controller 默认值\n       'a'=>'index', //action 默认值,\n       'isRewrite'=> TRUE //是否开启伪静态 .htaccess 文件配置\n    ),\n```\n其中 m 为模块，一般我们开发小型web系统时候，后台（admin）、前端（web）、接口(api) 来划分结构； 大型一点的web系统，常根据业务进行模块划分，比如\nshop、order、user 等等模块划分。 实际划分就对应着 controller view 里面的文件夹的安排，一般的 一个模块对应其下面的一个文件夹，这样清晰的管理模块\n方便协作开发和解耦\n\n另外 配置中 m=>[api..] 数组就是划分的模块，对应地址栏会去选择 www.baidu.com/admin/con/index  域名部分后面的第一个 /admin/ 如果在配置中就表示为识别到的模块， 否者将模块默认为 m[0]\n实现代码可以参考 es：\n\n```php\n$rewrite = $GLOBALS['rewrite'];\nif ($rewrite['isRewrite']) {\n    $route = explode(\"/\", $_SERVER['PHP_SELF']);\n    if (!empty($rule[1])) {\n        if (in_array($rule[1], $rewrite['m'])) {\n            $_GET['m'] = $route[1];\n            list($_GET['c'], $_GET['a']) = array_slice($route, 2, 3);\n        } else {\n            $_GET['m'] = $rewrite['m'][0];\n            list($_GET['c'], $_GET['a']) = array_slice($route, 1, 2);\n        }\n    }\n}\n```\n\n#### 数据库配置\n\n数据库目前支持mysql\n\n```php\n$dbb = array(\n    'mysql' => [\n        //主库\n        'master'=>[\n            'MYSQL_HOST' => '127.0.0.1',\n            'MYSQL_PORT' => '3306',\n            'MYSQL_USER' => 'root',\n            'MYSQL_DB' => 'db_demo',\n            'MYSQL_PASS' => '123456',\n            'MYSQL_CHARSET' => 'utf8',\n        ],\n        //从库可以加入多个实例\n        'slave'=>[\n            'MYSQL_HOST' => '127.0.0.1',\n            'MYSQL_PORT' => '3306',\n            'MYSQL_USER' => 'root',\n            'MYSQL_DB' => 'db_demo',\n            'MYSQL_PASS' => '123456',\n            'MYSQL_CHARSET' => 'utf8',\n        ]\n    ],\n    'prefix' => 'mo_',\n);\n```\n#### 业务自定义配置\n \n 自定义的业务方面的配置，可以自己定义个配置文件，在config.php 进行引入，也可以直接在config.php 进行修改配置添加节点，后面使用全部用\n \n $GLOBALS = require(APP_PATH . '../config.php');\n$GLOBALS 全局 数组配置进行获取相应的配置项。\n\n### 核心实现文件（Helper.php）\n```php\n /**\n * 获取规则的url,统一获取url方便路由规则的对应\n * @param $c\n * @param $a\n * @param array $param\n * @return string\n */\npublic static function url($c, $a, $param = array())\n\n /**\n * 启动程序，实现了mvc的核心逻辑（根据 c , a 参数怎样去对应执行相应的controller）\n */\npublic static function start()\n\n/**\n * 所有的输出格式统一\n * @param $message 输出对象\n * @param $code 输出错误码\n */\npublic static function responseJson($message, $code = 0)\n\n\n/** 在操作完成一个事务的时候，引导调整到下一个事务，支出ajax的请求返回\n * @param $msg\n * @param string $url\n * @param int $code 非0 错误提示\n */\npublic static function redirect($msg,  $url = '',$code= 0)\n\n\n /** 打印文件日志方便显示调试\n * @param $errmsg\n * @param $level debug, info, error 基本类似log4\n */\npublic static function log($errMsg, $level = 'info')\n\n\n/**\n * request获取信息设置默认值（特别的 $_GET['**'] 不存在的参数会notice,此函数很好解决了这个问题）\n * @param $name\n * @param $defult\n * @return mixed\n */\npublic static function request($name, $defult)\n\n```\n\n### 控制器\n\n#### Controller\n\n控制器 （Get, Post , Head , Put ）+$_Get['a'] 的函数，直接暴露给了请求，请求可以通过\n$_GET['a'] 直接调用，如果么没有指定相应http 动作时间，直接调用 public action+$_GET['a'] 的函数\n比如 客户端get请求\n    \n    /api/main/index\n    会路由到 controller/api/mainController.php 文件 下面 的 \n    public function getIndex(){} 函数，如果此函数不存在，会找个 \n    public function actionIndex(){} 函数\n\n另外在写http 接口时候我们可以直接 Restful api 格式用http 请求自动对应\n比如\n\n    /api/good\n    会路由到 controller/api/goodController.php 文件 下面 的 \n    public function get(){} 函数\n    public function post(){} 函数\n    ....已至restful Api接口写法\n\n```php\n//获取视图数据源的值\npublic function __get ($name)\n\n//此函数设置的值可以在视图模板里直接使用\npublic function __set ($name, $value)\n\n//处理 action对应的模板 $tpl_name 模板地址 会自定到view 和controller 同名的文件夹 默认 $c/$a.php\npublic function display ($tpl_name = \"\", $return = false)\n\n```\n\n#### baseController\n\nbaseController 在每个模块里面有父类，继承系统核心Controller 主要用来处理\n\n - 处理模块常用的业务（比如权限验证）\n - 处理比如分页的数据展现样式\n - 公共的业务处理在默认情况下没有model 那么把处理一些公共的数据操作业务也可以放到这里\n - 做数据输出的过滤，比如同一个输入格式 {\"code\":0,\"message\":\"\"} 诸如此类函数的处理\n \n### 数据模型\n\nes 数据库操作使用PDO pdo 本身对数据库操作，参数化，防止sql注入， 请在使用元素sql 语句查询的时候，不要直接拼凑字符串。\n\n### 模型类\n\n模型类继承 Model 一般情况下可以不需要模型类之间在Action里面进行数据库操作，当我们某些业务数据库操作部分其他公用起来，那么模型类是不错的选择。\n\n```php\nclass User extends Model\n{\n    //模型对应的表名\n    public $table_name = 'user_view';\n\n    //定义使用的常用\n    const  USER_ON = 0; \n    const  USER_OFF = 1; \n\n    //定义数据的一些枚举\n    public static  $member =[\n        self::USER_ON => '正常',\n        self::USER_OFF => '禁用'\n    ];\n    \n    //公用的操作数据方法\n    public function login($username, $password)\n    {\n        $this->find()\n        //todo \n    }\n }\n //直接实例等同 $userDb = new Model('user') 只不过模型里面只能用到原始的Model表;\n $userDb = new User();\n```\n\n#### 读写分离（多数库操作）\n\n```php\n\n public function setDB($db_config_key = 'default', $is_readonly = false)\n\n $userDb = new Model('user');\n \n//设置以下操作使用 sale0 实例\n $userDb->setDb('sale0', true);\n $user->...\n\n```\n\n#### 查询\n\n```php\n//查询user表数据\n$userDb = new Model(\"user\");\n\n /** 查询数据返回数据数组集合\n     * @param array 查询条件可以是数组，也可以直接是字符串 比如 ['id'=>1] 等效 \"and id = 1\"\n     * @param null 排序 如 \" id desc\"\n     * @param string 查詢表字段\n     * @param null $limit 这个参数比较关键，如果这个参数不为空将 可以分页\n     * @return mixed\n     */\npublic function findAll ($conditions = array(), $sort = null, $fields = '*', $limit = null) \n\n//分页查询\n$userData = $userDb->findAll('id> 1', 'id desc', '*', 10)\n\n//执行为上面的语句后\n$userDb->page 返回一个分页数组，模板里面可以根据这个数组去做一定处理\n一般情况BaseController 自定义个函数来拼凑html 显示\n或者直接 是前后端分离 json 直接打印给前端处理\n \n//查询单条数据\npublic function find ($conditions = array(), $sort = null, $fields = '*')\n\n//sql 直接查询(注意参数化形式不要直接拼凑sql)\npublic function query($sql, $params = array())\n$user = $userDb->query(\"select * from mo_user where id=:id \", [':id'=>1]);\n\n//查询统计量等同于 sum($field) 返回直接返回整型\npublic function findSum($conditions, $field)\n\n//查询统计量等同于 count(1) 返回直接返回整型\npublic function findCount($conditions)\n\n```\n#### 各种函数的查询条件\n```sql\n方式一： 拼凑sql\n\n $user->find(\" username='{$username}' and sex > $sex\")\n \n方式二： 简单数组实现and 连接\n\n$user->find(['username'=>$username, 'sex>'=>$sex])\n\n方式三： 参数化写法（类似 上面的query 函数方式）\n\n$user->find([ \"username = :username and sex > :sex and id in (:ids)\" , [':username'=>$username, ':sex'=>$sex, ':ids'=>[1,3,4,..] ] ])\n\n方式一 可能为存在sql注入问题 特别注意， 方式二简单明了，但是连接 or 条件 为能实现 方式三稍微复杂 建议使用\n```\n\n\n####  新增\n\n```php\n/** 表插入记录\n * @param $row\n * @return mixed\n */\npublic function create($row);\n\n演示\n$userDb = new Model('user');\n//插入单条记录\n$userDb->create(\n    ['username'=>'es',\n      'password'=>'123456',\n      'sex'=>1,\n      '#created'=>'CURRENT_TIMESTAMP()' //带#的key 后面的value 可以直接是mysql 内置函数\n    ]\n);\n\n批量插入\n$userDb->create(\n    [\n        ['username'=>'es',password'=>'123456','#created'=>'CURRENT_TIMESTAMP()'],\n        ['username'=>'es',password'=>'1234564', '#created'=>'CURRENT_TIMESTAMP()' ]...\n    ]\n);\n\n```\n#### 更新\n```php\n/**\n * @param 查询条件\n * @param 更加的数据\n * @return mixed\n */\npublic function update($conditions, $row)\n$userDb->update(\n    ['id'=>1],\n    ['username'=>'es',\n      'password'=>'123456',\n      '+sex'=>1, // 操作符号支持 + - * / 转换成sql  sex = sex+1\n      '#created'=>'CURRENT_TIMESTAMP()' //支持mysql 函数\n    ]\n);\n```\n\n#### 删除\n```php\n//按条件删除数据\npublic function delete($conditions)\n\n$userDb = new Model('user');\n$userDb->delete(['id'=>1]);\n\n```\n\n\n#### 事务\n```php\n $Db = Model::startTrans();\n $userDb = new User();\n ......\n $Db->commit()\n\n```\n\n\n### 视图\nes 采用php原始 脚本作为模板标记语言， 主要好处有\n- 不需要额外学习一门新的标识语言\n- 速度上也是最快的\n- 实现起来简单\n\n#### 模板引擎\n    php 原始脚本，只不过模板里面能够使用的变量 只能来源controller __set 所设置的变量\n    保证模板使用的数据安全，按需所给。\n    \n2. 母版\n    \n   引入母版机制(具体参考案例)\n ```html\n<?php include $_view_obj->compile($__template_file); ?>\n```\n    \n## 扩展引用\nes 本身最求灵活，极简单，所有没有引入其他重型模板的功能点，比如 cache 、http 等常用模块，那么使用者，如果需要\n相关功能怎么办能\n\n步骤如下：\n\n- 配置扩展目录\n```php\n'plugins'=>['include','plugin'] //扩展目录\n```\n- 扩展目录里面放入扩展类[类文件直拷贝到目录里面]\n```php\nclass P\n{\n    public function test(){\n        return '扩展';\n    }\n}\n\n```\n- 在controller action 里面\n\n```php\n$p = new P();\n$p->test()\n```\n    同理静态方法调用跟为方便\n\n ## composer 机制扩展\n   \n现实开发中大部分功能模块通过composer 安装进去 扩展我们的功能，这是非常棒的选择。具体建议做法\n \n 1 . index.php 里面引入 \n ```php\n  require_once (__DIR__.'/vendor/autoload.php');\n ``` \n \n 2 . plugin 里面做个静态类 比如 App.php\n \n ```php\n  use RedisClient\\RedisClient;\n  class App\n  {\n      private static $_redis;\n      /**\n       * 缓存实现\n       */\n      public static function redis()\n      {\n          if (empty(self::$_redis)) {\n              self::$_redis = new RedisClient($GLOBALS['redis']);\n          }\n          return self::$_redis;\n      }\n ```\n \n 3 . 配置文件加入config 构造需要的参数 \n \n ```php\n  'redis'=>[\n         'server' => '192.168.1.61:6379',\n         'timeout' => 2,\n         'password' => 'songfeiok',\n         'database' => 3,\n     ],\n ```\n \n 3 . 使用\n \n```php\n    $redisClient = App::redis()\n    $redisClient->set(\"A\", 1)\n    $redisClient->get(\"A\")\n     .....\n```\n \n\n## 支持常驻脚本\n\n```php\n//能处理shell 请求\nif (!empty($argc)) {\n    $_REQUEST['m'] = $argv[1];\n    $_REQUEST['c'] = $argv[2];\n    $_REQUEST['a'] = $argv[3];\n    $_REQUEST['p'] = empty($argv[4])? '': $argv[4];\n}\n\n$ php index.php m c a \"自定义参数\"\n```\n    注意 在脚本的 action 跟 web 有区别，shell的controller 能执行的函数是 action前缀的方法，比如 MainController -> actionIndex\n\n## 联系方式\n\n* bug和建议请发送至：`313690636@qq.com`；\n* 技术支持、技术合作或咨询请联系作者QQ:`313690636`、群：`571627871`。\n* 博客地址 ：http://www.cnblogs.com/echosong/\n\n\n  [1]:http://dbbsale.oss-cn-shanghai.aliyuncs.com/keqiang/32.ico\n\n\n"
  },
  {
    "path": "index.php",
    "content": "<?php\n\ndefine('APP_DIR', realpath('./'));\n//加载composer 信息\nif(file_exists(__DIR__.'/vendor/autoload.php')){\n    require_once __DIR__.'/vendor/autoload.php';\n}\n//能处理shell 请求\nif (!empty($argc)) {\n    $_REQUEST['m'] = $argv[1];\n    $_REQUEST['c'] = $argv[2];\n    $_REQUEST['a'] = $argv[3];\n    $_REQUEST['p'] = empty($argv[4])? '': $argv[4];\n}\n\nrequire(APP_DIR . '/src/core/es.php');\n"
  },
  {
    "path": "res/css/style.css",
    "content": "*,body {\n    margin: 0px;\n    padding: 0px;\n}\n\nbody {\n    margin: 0px;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 14px;\n    line-height: 20px;\n    background-color: #fff;\n}\n\nheader,\nfooter {\n    width: 960px;\n    margin-left: auto;\n    margin-right: auto;\n}\n\n.logo {\n    background-image: url('data:image/png;base64,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');\n    background-repeat: no-repeat;\n    -webkit-background-size: 100px 100px;\n    background-size: 100px 100px;\n    background-position: center center;\n    text-align: center;\n    font-size: 42px;\n    padding: 250px 0 70px;\n    font-weight: normal;\n    text-shadow: 0px 1px 2px #ddd;\n}\n\nheader {\n    padding: 100px 0;\n}\n\nfooter {\n    line-height: 1.8;\n    text-align: center;\n    padding: 50px 0;\n    color: #999;\n}\n\n.description {\n    text-align: center;\n    font-size: 16px;\n}\n\na {\n    color: #444;\n    text-decoration: none;\n}\n\n.backdrop {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    box-shadow: inset 0px 0px 100px #ddd;\n    z-index: -1;\n    top: 0px;\n    left: 0px;\n}"
  },
  {
    "path": "src/config.php",
    "content": "<?php\n\n$config = array(\n    'rewrite' => array(\n        //设置模块 碰到 http://{host}/admin/ 认为进入了后台模块 数组 0 标识默认 m\n        'm' => ['web', 'admin', 'app', 'api'],\n        'c' => 'main', //controller 默认值\n        'a' => 'index', //action 默认值,\n        'isRewrite' => true //是否开启伪静态 .htaccess 文件配置\n    ),\n    'debug' => true,\n    'plugins' => ['include', 'plugin'], //扩展目录\n    'static' => \"res\",\n    'logPath' => 'logs', //日志路径，请保证路径权限可写\n    'startSession' => false, //session 默认不开启\n    'limitMax' => 1000 //保护数据库以免一失误导致大查询\n);\n\n$dbb = array(\n    'mysql' => [\n        //主库\n        'master' => [\n            'MYSQL_HOST' => '127.0.0.1',\n            'MYSQL_PORT' => '3306',\n            'MYSQL_USER' => 'root',\n            'MYSQL_DB' => 'db_yxbd',\n            'MYSQL_PASS' => '',\n            'MYSQL_CHARSET' => 'utf8',\n        ],\n        //从库可以加入多个实例\n        'slave' => [\n            'MYSQL_HOST' => '127.0.0.1',\n            'MYSQL_PORT' => '3306',\n            'MYSQL_USER' => 'root',\n            'MYSQL_DB' => 'db_yxbd',\n            'MYSQL_PASS' => '123456',\n            'MYSQL_CHARSET' => 'utf8',\n        ]\n    ],\n    'prefix' => 'tb_',\n);\n\nreturn $dbb + $config;\n"
  },
  {
    "path": "src/controller/shell/BaseController.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: Administrator\n * Date: 2017/10/13\n * Time: 20:29\n */\n\nclass BaseController extends  Controller\n{\n    public function init()\n    {\n\n    }\n}"
  },
  {
    "path": "src/controller/shell/MainController.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: echosong\n * Date: 2017/9/10\n * Time: 12:21\n */\n\nclass MainController extends BaseController\n{\n    /**\n     * php 脚本运行 php index.php shell main index \"自定义参数\"\n     */\n    public function actionIndex()\n    {\n        while (true){\n            //todo\n            echo \"fdsfdsfds\";\n            sleep(1);\n        }\n    }\n}"
  },
  {
    "path": "src/controller/web/BaseController.php",
    "content": "<?php\n\nClass BaseController extends Controller\n{\n\n\n    /**\n     * 初始化 action 执行之前执行\n     */\n    public function init()\n    {\n        $this->layout = \"layout.php\";\n    }\n\n    /**\n     * 统一输出下分页\n     */\n    function pager($pageArr, $param = \"\")\n    {\n        if ($param != '') {\n            $param = '&' . $param;\n        }\n        if (!$pageArr['all_pages']) {\n            return \"\";\n        }\n        $pageStr = '';\n        $pageStr .= '</span> 条记录' . ' <span>共  <span style=\"color: #92d2ff;\">' . $pageArr['total_count'] . $pageArr['total_page'] . ' 页 </span>&nbsp; ';\n        $current = $pageArr['current_page'];\n        if ($current > 1) {\n            $pageStr .= '<a href=\"?page=1' . $param . '\">首页</a>&nbsp;<a href=\"?page=' . strval($current - 1) . $param . '\">上一页</a>';\n        } else {\n            $pageStr .= '<span>首页</span><span>上一页</span>';\n        }\n        foreach ($pageArr['all_pages'] as $p) {\n            if ($p == $current) {\n                $pageStr .= '<span> &nbsp;' . strval($p) . '&nbsp;</span>';\n            } else {\n                $pageStr .= '<a href=\"?page=' . strval($p) . $param . '\">&nbsp;' . strval($p) . '&nbsp;</a>';\n            }\n        }\n        if ($current < $pageArr['total_page']) {\n            $pageStr .= '<a href=\"?page=' . strval($current + 1) . $param . '\">下一页</a>&nbsp;<a href=\"?page=1' . $param . '\">末页</a>';\n        } else {\n            $pageStr .= '<span>下一页</span><span>末页</span>';\n        }\n\n        return $pageStr;\n\n    }\n}\n"
  },
  {
    "path": "src/controller/web/MainController.php",
    "content": "<?php\n\n\nclass MainController extends BaseController\n{\n    public function getLogin()\n    {\n\n    }\n\n    private function uplod()\n    {\n\n    }\n\n    /**\n     * 测试分页\n     */\n    public function getPage(){\n        $userDb = new Model('category');\n        $page = Helper::request('page', 0);\n        $users = $userDb->findAll('', 'id desc',  'id,name', [$page, 20]);\n        Helper::responseJson([$users, $userDb->page ]);\n    }\n\n    public function getIndex()\n    {\n\n        $this->display('default.php');\n    }\n\n    public function postIndex()\n    {\n        //sleep(6);\n       var_dump($_REQUEST);\n    }\n\n    public function getTest()\n    {\n        $userDb = new Model('user');\n        $id = $userDb->create([\n            [\n                'username' => 'admin6',\n                'password' => 'password1',\n                'login_count' => 1,\n                '#last_time' => 'CURRENT_TIMESTAMP()'\n            ],\n            [\n                'username' => 'admin8',\n                'password' => 'password1',\n                'login_count' => 1,\n                '#last_time' => 'CURRENT_TIMESTAMP()'\n            ]\n        ]);\n        echo $userDb->update(['id' => 1],\n            ['+login_count' => 10, \"#email\" => 'uuid()']);\n\n    }\n\n\n}"
  },
  {
    "path": "src/core/controller.php",
    "content": "<?php\r\n\r\n\r\nclass Controller\r\n{\r\n    public $layout;\r\n    private $_v;\r\n    private $_data = array();\r\n    public $routes;\r\n    public $template_dir ;\r\n\r\n    public function init() { }\r\n\r\n    public function __construct()\r\n    {\r\n        global $__module, $__controller, $__action;\r\n        $this->routes = ['m' => $__module, 'c' => $__controller, 'a' => $__action];\r\n        $this->template_dir =  APP_DIR . DS . \"src\" . DS . 'view' . DS . $this->routes['m'];\r\n        $this->init();\r\n    }\r\n\r\n    public function __get($name)\r\n    {\r\n        return $this->_data[$name];\r\n    }\r\n\r\n    public function __set($name, $value)\r\n    {\r\n        $this->_data[$name] = $value;\r\n    }\r\n\r\n    public function display($tpl_name=\"\", $return = false)\r\n    {\r\n        if(empty($tpl_name)){\r\n            $tpl_name = $this->routes['c'].DS.$this->routes['a'].\".php\";\r\n        }\r\n        if (!$this->_v) {\r\n            $this->_v = new View();\r\n        }\r\n        //controller 成员对模板外公开\r\n        $this->_v->assign(get_object_vars($this));\r\n        $this->_v->assign($this->_data);\r\n\r\n        if ($this->layout) {\r\n            $this->_v->assign('__render_body',  $this->template_dir . DS . $tpl_name);\r\n            $tpl_name = $this->layout;\r\n        }\r\n        if ($return) {\r\n            //此方式保留方便action里面直接生成静态文件\r\n            return $this->_v->render( $this->template_dir . DS . $tpl_name);\r\n        } else {\r\n            echo $this->_v->render( $this->template_dir . DS . $tpl_name);\r\n        }\r\n    }\r\n\r\n}"
  },
  {
    "path": "src/core/es.php",
    "content": "<?php\r\ndefined('DS') or define('DS', DIRECTORY_SEPARATOR);\r\ndefine('APP_ROOT', '/');\r\ndefine('APP_PATH', dirname(__FILE__) . DS);\r\n\r\nDate_default_timezone_set(\"PRC\");\r\n$GLOBALS = require(APP_PATH . '../config.php');\r\n\r\nif(!empty($GLOBALS['startSession'])){\r\n    session_start();\r\n}\r\n\r\nrequire_once(APP_PATH . \"helper.php\");\r\nrequire_once(APP_PATH . \"controller.php\");\r\nrequire_once(APP_PATH . \"model.php\");\r\nrequire_once(APP_PATH . \"view.php\");\r\n\r\nset_error_handler( [\"Helper\", \"customError\"]);\r\nregister_shutdown_function(function (){\r\n    $fatalMsg = error_get_last();\r\n    if($fatalMsg){\r\n        Helper::log(json_encode($fatalMsg),  Helper::FATAL_ERROR);\r\n    }\r\n});\r\n\r\n//设置路由规范\r\nHelper::setRoute();\r\n\r\n//定义全局变量\r\n$__module = $_REQUEST['m'];\r\n$__controller = $_REQUEST['c'];\r\n$__action = $_REQUEST['a'];\r\n\r\nspl_autoload_register(function ($class) use ($__module) {\r\n    foreach (array_merge($GLOBALS['plugins'], ['model', 'controller' . DS . $__module, './']) as $dir) {\r\n        $file = APP_PATH . '../' . $dir . DS . $class . '.php';\r\n        if (file_exists($file)) {\r\n            include $file;\r\n        }\r\n    }\r\n});\r\n\r\n//开始运行\r\nHelper::start();"
  },
  {
    "path": "src/core/helper.php",
    "content": "<?php\n\nClass Helper\n{\n    //致命错误级别\n    const FATAL_ERROR = 'fatal_error';\n\n    /**\n     * 检查参数合法性\n     * @param $name\n     * @return int\n     */\n    public static function is_available_classname($name)\n    {\n        return preg_match('/[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/', $name);\n    }\n\n    /**\n     * 获取规则的url\n     * @param $c\n     * @param $a\n     * @param array $param\n     * @return string\n     */\n    public static function url($c, $a, $param = array())\n    {\n        GLOBAL $__module;\n        GLOBAL $GLOBALS;\n        $rewrite = $GLOBALS['rewrite'];\n        $c = empty($c) ? $rewrite['c'] : $c;\n        $a = empty($a) ? $rewrite['a'] : $a;\n        $params = empty($param) ? '' : http_build_query($param);\n        if($_SERVER['SERVER_PORT'] ==443){\n            $protocol = 'https';\n        }else{\n            $protocol = 'http';\n        }\n        if ($rewrite['isRewrite']) {\n            if (!empty($params)) {\n                $params = \"?$params\";\n            }\n            if ($__module == $rewrite['m'][0]) {\n                $url = \"$protocol://\" . $_SERVER[\"HTTP_HOST\"] . '/' . $c . '/' . $a . $params;\n            } else {\n                $url = \"$protocol://\" . $_SERVER[\"HTTP_HOST\"] . '/' . $__module . '/' . $c . '/' . $a . $params;\n            }\n        } else {\n            if ($__module != $rewrite['m'][0]) {\n                $url = \"$protocol://\" . $_SERVER[\"SCRIPT_NAME\"] . \"?m=$__module&c=$c&a=$a$params\";\n            } else {\n                $url = \"$protocol://\" . $_SERVER[\"SCRIPT_NAME\"] . \"?c=$c&a=$a$params\";\n            }\n        }\n        return $url;\n    }\n\n    /**\n     * 设置路由\n     */\n    public static function setRoute()\n    {\n        $rewrite = $GLOBALS['rewrite'];\n        $list_route = [$rewrite['m'][0], $rewrite['c'], $rewrite['a']];\n        if ($rewrite['isRewrite'] && isset($_SERVER['REQUEST_URI'])) {\n            $requestURI = $_SERVER['REQUEST_URI'];\n            $requestURI = str_replace('?' . $_SERVER[\"QUERY_STRING\"], '', $requestURI);\n            $route = explode(\"/\", $requestURI);\n            if (in_array($route[1], $rewrite['m'])) {\n                $list_route[0] = $route[1];\n                $route = array_slice($route, 1, count($route));\n            }\n            $list_route[1] = empty($route[1]) ? $list_route[1] : $route[1];\n            $list_route[2] = empty($route[2]) ? $list_route[2] : $route[2];\n        }\n        $_REQUEST['m'] = strtolower(self::request(\"m\", $list_route[0]));\n        $_REQUEST['c'] = strtolower(self::request(\"c\", $list_route[1]));\n        $_REQUEST['a'] = strtolower(self::request(\"a\", $list_route[2]));\n    }\n\n    /**\n     * 启动程序\n     */\n    public static function start()\n    {\n        GLOBAL $__module, $__action, $__controller;\n\n        //模块对应目录\n        if (!self::is_available_classname($__module)) {\n            die(\"Err: Module name '$__module' is not correct!\");\n        }\n        if (!is_dir(APP_PATH . '../controller' . DS . $__module)) {\n            self::responseJson(\"Err: Module '$__module' is not exists!\", 404);\n        }\n\n        if (!self::is_available_classname($__controller)) {\n            self::responseJson(\"Err: Controller name '$__controller' is not correct!\", 404);\n        }\n        $controller_name = $__controller . 'Controller';\n        //处理restful\n        $httpMethod = strtolower(empty($_SERVER['REQUEST_METHOD']) ? 'get' : $_SERVER['REQUEST_METHOD']);\n        $action_name = $httpMethod . ucfirst($__action);\n\n        if (!class_exists(ucfirst($controller_name), true)) {\n            self::responseJson(\"Err: Controller '$controller_name' is not exists!\", 404);\n        }\n        $controller_obj = new $controller_name();\n\n        if (!method_exists($controller_obj, $action_name)) {\n            $action_name = 'action' . $__action;\n            if (!method_exists($controller_obj, $action_name)) {\n                self::responseJson(\"Err: Method '$action_name' of '$controller_name' is not exists!\", 404);\n            }\n        };\n        $controller_obj->$action_name();\n    }\n\n    /**\n     * 所有的输出格式统一 支持shell 输出\n     * @param $message 输出对象\n     * @param $code 输出错误码\n     */\n    public static function responseJson($message, $code = 0)\n    {\n        if (PHP_SAPI === 'cli') {\n            printf(\"[%s] %s\", date('Y/m/d H:i:s'), $message . PHP_EOL);\n        } else {\n            header('x-powered-by:ES.1.0');\n            header('Content-type: application/json');\n            exit(json_encode(['code' => $code, 'message' => $message]));\n        }\n    }\n\n    /**\n     * @param $msg\n     * @param string $url\n     * @param int $code 非0 错误提示\n     */\n    public static function redirect($msg, $url = '', $code = 0)\n    {\n        if (isset($_SERVER[\"HTTP_X_REQUESTED_WITH\"]) && strtolower($_SERVER[\"HTTP_X_REQUESTED_WITH\"]) == \"xmlhttprequest\") {\n            if (is_array($msg)) {\n                exit(json_encode($msg));\n            } else {\n                self::responseJson(['alertStr' => $msg, 'redirect' => $url], $code);\n            }\n        } else {\n            $strAlert = \"\";\n            if (!empty($msg)) {\n                $strAlert = \"alert(\\\"{$msg}\\\");\";\n            }\n            if ($url == \"\") {\n                exit(\"<script>alert('$msg');window.history.go(-1);</script>\");\n            } else {\n            }\n            exit(\"<html><head><meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\"><script>function sptips(){  {$strAlert} location.href=\\\"{$url}\\\";}</script></head><body onload=\\\"sptips()\\\"></body></html>\");\n        }\n    }\n\n    /**\n     * 获取客户端ip\n     * @return array|false|string\n     */\n    public static function userIp()\n    {\n        if (getenv(\"HTTP_CLIENT_IP\")) {\n            $ip = getenv(\"HTTP_CLIENT_IP\");\n        } else {\n            if (getenv(\"HTTP_X_FORWARDED_FOR\")) {\n                $ip = getenv(\"HTTP_X_FORWARDED_FOR\");\n            } else {\n                if (getenv(\"REMOTE_ADDR\")) {\n                    $ip = getenv(\"REMOTE_ADDR\");\n                } else {\n                    $ip = \"Unknow\";\n                }\n            }\n        }\n        return $ip;\n    }\n\n    /** 日志记录\n     * @param $errMsg\n     * @param $level (debug, info, error)\n     */\n    public static function log($errMsg, $level = 'info')\n    {\n        if(!is_string($errMsg)){\n            $errMsg = json_encode($errMsg);\n        }\n        //shell 的操作权限跟web不一样，所以需要区分\n        global $__module;\n        $logPath = APP_DIR . DS . $GLOBALS['logPath'] . DS . $level .\n            \"_\".$__module. date('Ymd') . \".log\";\n        error_log(date('Ymd H:i:s') . \"  \" . $errMsg . PHP_EOL, 3, $logPath);\n        if (strtolower(trim($level)) === 'fatal_error') {\n            if ($GLOBALS['debug']) {\n                Helper::responseJson($errMsg, 500);\n            } else {\n                Helper::responseJson('异常查看系统日志', 500);\n            }\n        }\n    }\n\n    /** 自定义错误\n     * @param $errNo (错误码)\n     * @param $errStr (错误说明)\n     * @param $errFile 错误文件\n     * @param $errLine 错误行号\n     */\n    public static function customError($errNo, $errStr, $errFile, $errLine)\n    {\n        $errMsg = \"[{$errNo}] {$errStr} {$errFile} {$errLine} \";\n        if ($errNo == E_ERROR) {\n            $errNo = 'fatal_error';\n        }\n        self::log($errMsg, $errNo);\n        if ($GLOBALS[\"debug\"]) {\n            echo $errMsg;\n        }\n    }\n\n    /**request获取信息设置默认值\n     * @param $name\n     * @param $default\n     * @param bool $isSafe\n     * @return mixed\n     */\n    public static function request($name, $default, $isSafe = true)\n    {\n        if (!isset($_REQUEST[$name])) {\n            return $default;\n        } else {\n            return $isSafe ? str_replace(\"''\", \"\", $_REQUEST[$name]) : $_REQUEST[$name];\n        }\n    }\n\n    /** 字段过滤\n     * @param array $input\n     * @param $fields\n     */\n    public static function filterFields(array &$input, $fields)\n    {\n        $operator = ['*', '+', '-', '/', '#'];\n        if (empty($fields)) {\n            return;\n        }\n        foreach ($input as $k => $v) {\n            $key = $k;\n            if (in_array(substr($k, 0, 1), $operator)) {\n                $key = substr($k, 1);\n            }\n            if (!in_array($key, $fields)) {\n                unset($input[$k]);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/core/model.php",
    "content": "<?php\r\n\r\nclass Model\r\n{\r\n    public $page;\r\n    public $table_name;\r\n    public $view_name;\r\n    public $fields;\r\n    private $_model;\r\n\r\n    private $_master_db;\r\n    private $_slave_db;\r\n    private $sql = array();\r\n\r\n    public function __construct($table_name = null)\r\n    {\r\n        global $GLOBALS;\r\n        if ($table_name) {\r\n            $this->table_name = $GLOBALS['prefix'] . $table_name;\r\n        }\r\n        if (empty($this->table_name)) {\r\n            $this->table_name = $this->view_name;\r\n        } else {\r\n            if (substr($this->table_name, 0, strlen($GLOBALS['prefix'])) != $GLOBALS['prefix']) {\r\n                $this->table_name = $GLOBALS['prefix'] . $this->table_name;\r\n            }\r\n        }\r\n    }\r\n    /** 开启事务并处理业务 */\r\n    public static function transaction( $fn){\r\n        $db = self::startTrans();\r\n        try {\r\n            $res = $fn();\r\n            $db->commit();\r\n            return $res;\r\n        }catch (Throwable $e){\r\n            $db->rollback();\r\n            $code = $e->getCode();\r\n            if($code == 0){\r\n                $code = 500;\r\n            }\r\n            Helper::responseJson($e->getMessage(),$code);\r\n        }\r\n    }\r\n\r\n\r\n    public function __get($name)\r\n    {\r\n        if (empty($this->_model[$name])) {\r\n            return null;\r\n        } else {\r\n            return $this->_model[$name];\r\n        }\r\n    }\r\n\r\n    public static function startTrans(){\r\n        $db = $GLOBALS['mysql_instances']['default'];\r\n        if($db == null){\r\n            $db = (new Model())->setDB();\r\n        }\r\n        $db->beginTransaction();\r\n        return $db;\r\n    }\r\n    public function findAll($conditions = array(), $sort = null, $fields = '*', $limit = null)\r\n    {\r\n        $sort = !empty($sort) ? ' ORDER BY ' . $sort : '';\r\n        $conditions = $this->_where($conditions);\r\n        $sql = ' FROM ' . $this->table_name . $conditions[\"_where\"];\r\n        if (is_array($limit)) {\r\n            $total = $this->query('SELECT COUNT(*) as M_COUNTER ' . $sql, $conditions[\"_bindParams\"]);\r\n            $limit = $limit + array(1, 20, 10);\r\n            $limit = $this->pager($limit[0], $limit[1], $limit[2], $total[0]['M_COUNTER']);\r\n            $limit = empty($limit) ? '' : ' LIMIT ' . $limit['offset'] . ',' . $limit['limit'];\r\n        } else {\r\n            $limit_max = empty($GLOBALS[\"limitMax\"]) ?1000: $GLOBALS['limitMax']  ;\r\n            if (empty($limit)) {\r\n                $limit = \" LIMIT {$limit_max}\";\r\n            } else {\r\n                $limit = intval($limit_max) < $limit ? \" LIMIT {$limit_max} \" : \" LIMIT {$limit} \";\r\n            }\r\n        }\r\n        $_data = $this->query('SELECT ' . $fields . $sql . $sort . $limit, $conditions[\"_bindParams\"]);\r\n        if ($_data == null) {\r\n            return [];\r\n        } else {\r\n            return $_data;\r\n        }\r\n    }\r\n\r\n    public function find($conditions = array(), $sort = null, $fields = '*')\r\n    {\r\n\r\n        $res = $this->findAll($conditions, $sort, $fields, 1);\r\n        if (!empty($res)) {\r\n            $this->_model = array_pop($res);\r\n            return $this->_model;\r\n        } else {\r\n            return false;\r\n        }\r\n    }\r\n\r\n    public function update($conditions, $row)\r\n    {\r\n        $values = [];\r\n        Helper::filterFields($row, $this->fields);\r\n        foreach ($row as $k => $v) {\r\n            $op = substr($k, 0, 1);\r\n            if ($op == \"+\" || $op == \"-\" || $op == \"*\" || $op == \"/\") {\r\n                $k = substr($k, 1);\r\n                $set_value[] = '`' . $k . \"`= {$k}{$op}{$v}\";\r\n                continue;\r\n            }\r\n\r\n            if (strpos($k, '#') === 0) {\r\n\r\n                $set_value[] = '`' . substr($k, 1) . \"`=\" . $v;\r\n                continue;\r\n            }\r\n            $values[\":M_UPDATE_\" . $k] = str_ireplace('</script>','', $v);\r\n            $set_value[] = '`' . $k . \"`=\" . \":M_UPDATE_\" . $k;\r\n        }\r\n        //  var_dump($values);\r\n        $conditions = $this->_where($conditions);\r\n        return $this->execute(\"UPDATE \" . $this->table_name . \" SET \" . implode(', ',\r\n                                                                                $set_value) . $conditions[\"_where\"],\r\n                              $conditions[\"_bindParams\"] + $values);\r\n    }\r\n\r\n    public function delete($conditions)\r\n    {\r\n        $conditions = $this->_where($conditions);\r\n        return $this->execute(\"DELETE FROM \" . $this->table_name . $conditions[\"_where\"], $conditions[\"_bindParams\"]);\r\n    }\r\n\r\n    public function create($rows)\r\n    {\r\n        $keys = [];\r\n        $stack = [];\r\n        $map = [];\r\n        if (empty($rows[0])) {\r\n            $rows = [$rows];\r\n        }\r\n        foreach ($rows as $key => $row) {\r\n            Helper::filterFields($row, $this->fields);\r\n            $rows[$key] = $row;\r\n        }\r\n        foreach ($rows[0] as $k => $v) {\r\n            if (strpos($k, '#') === 0) {\r\n                $k = substr($k, 1);\r\n            }\r\n            $keys[] = \"`{$k}`\";\r\n        }\r\n        foreach ($rows as $key => $row) {\r\n            $values = [];\r\n            foreach ($row as $k => $v) {\r\n                if (strpos($k, '#') === 0) {\r\n                    $values[] = $v;\r\n                    continue;\r\n                }\r\n                $map_key = \":{$k}_{$key}\";\r\n                $values[] = $map_key;\r\n                $map[$map_key] = str_ireplace('</script>','', $v);\r\n            }\r\n            $stack[] = '(' . implode($values, ', ') . ')';\r\n        }\r\n        $sql = \"INSERT INTO \" . $this->table_name . \" (\" . implode(', ', $keys) . \") VALUES \" . implode(', ',\r\n                                                                                                        $stack);\r\n        $this->execute($sql, $map);\r\n        return $this->_master_db->lastInsertId();\r\n    }\r\n\r\n    public function findCount($conditions)\r\n    {\r\n        $conditions = $this->_where($conditions);\r\n        $count = $this->query(\"SELECT COUNT(*) AS M_COUNTER FROM \" . $this->table_name . $conditions[\"_where\"],\r\n                              $conditions[\"_bindParams\"]);\r\n        return isset($count[0]['M_COUNTER']) && $count[0]['M_COUNTER'] ? $count[0]['M_COUNTER'] : 0;\r\n    }\r\n\r\n    public function findSum($conditions, $field)\r\n    {\r\n        $conditions = $this->_where($conditions);\r\n        $sum = $this->query(\"SELECT sum({$field}) AS M_COUNTER FROM \" . $this->table_name . $conditions[\"_where\"],\r\n                            $conditions[\"_bindParams\"]);\r\n        return isset($sum[0]['M_COUNTER']) && $sum[0]['M_COUNTER'] ? $sum[0]['M_COUNTER'] : 0;\r\n    }\r\n\r\n    public function dumpSql()\r\n    {\r\n        return $this->sql;\r\n    }\r\n\r\n    public function pager($page, $pageSize = 10, $scope = 10, $total)\r\n    {\r\n        $this->page = null;\r\n        if ($total > $pageSize) {\r\n            $total_page = ceil($total / $pageSize);\r\n            $page = min(intval(max($page, 1)), $total);\r\n            $this->page = array(\r\n                'total_count' => $total,\r\n                'page_size' => $pageSize,\r\n                'total_page' => $total_page,\r\n                'first_page' => 1,\r\n                'prev_page' => ((1 == $page) ? 1 : ($page - 1)),\r\n                'next_page' => (($page == $total_page) ? $total_page : ($page + 1)),\r\n                'last_page' => $total_page,\r\n                'current_page' => $page,\r\n                'all_pages' => array(),\r\n                'offset' => ($page - 1) * $pageSize,\r\n                'limit' => $pageSize,\r\n            );\r\n            $scope = (int)$scope;\r\n            if ($total_page <= $scope) {\r\n                $this->page['all_pages'] = range(1, $total_page);\r\n            } elseif ($page <= $scope / 2) {\r\n                $this->page['all_pages'] = range(1, $scope);\r\n            } else {\r\n                $this->page['all_pages'] = range($page - $scope / 2, min($page + $scope / 2 - 1, $total_page));\r\n            }\r\n        }else{\r\n            $this->page = array(\r\n                'total_count' => $total,\r\n                'page_size' => $pageSize,\r\n                'total_page' => 1,\r\n                'first_page' => 1,\r\n                'prev_page' => 1,\r\n                'next_page' => 1,\r\n                'last_page' => 1,\r\n                'current_page' => $page,\r\n                'all_pages' => array(),\r\n                'offset' => ($page - 1) * $pageSize,\r\n                'limit' => $pageSize,\r\n            );\r\n        }\r\n        return $this->page;\r\n    }\r\n\r\n    public function query($sql, $params = array())\r\n    {\r\n\r\n        return $this->execute($sql, $params, true);\r\n    }\r\n\r\n    public function execute($sql, $params = array(), $is_query = false)\r\n    {\r\n        $this->sql[] = $sql;\r\n        if ($is_query && is_object($this->_slave_db)) {\r\n            $sth = $this->_slave_db->prepare($sql);\r\n        } else {\r\n            if (!($this->_master_db)) {\r\n                $this->setDB('default');\r\n            }\r\n            if (empty($this->_master_db)) {\r\n                return ;\r\n            }\r\n            $sth = $this->_master_db->prepare($sql);\r\n        }\r\n\r\n\r\n        if (is_array($params) && !empty($params)) {\r\n            foreach ($params as $k => &$v) {\r\n                $sth->bindParam($k, $v);\r\n            }\r\n        }\r\n\r\n        $bool = $sth->execute();\r\n        if ($bool) {\r\n            return $is_query ? $sth->fetchAll(PDO::FETCH_ASSOC) : $sth->rowCount();\r\n        }\r\n        $err = $sth->errorInfo();\r\n        if ($err[1] == 2006 || $err[1]  == 2013) {\r\n            $GLOBALS['mysql_instances']['default'] = null;\r\n        }\r\n        Helper::log('Database SQL: \"' . $sql . '\", ErrorInfo: ' . $err[2], Helper::FATAL_ERROR);\r\n    }\r\n\r\n    public function setDB($db_config_key = 'default', $is_readonly = false)\r\n    {\r\n        if ('default' == $db_config_key) {\r\n            $db_config = $GLOBALS['mysql']['master'];\r\n        } else {\r\n            if (!empty($GLOBALS['mysql'][$db_config_key])) {\r\n                $db_config = $GLOBALS['mysql'][$db_config_key];\r\n            } else {\r\n                Helper::log(\"Database Err: Db config '$db_config_key' is not exists!\", Helper::FATAL_ERROR);\r\n            }\r\n        }\r\n        if ($is_readonly) {\r\n            return  $this->_slave_db = $this->_db_instance($db_config, $db_config_key);\r\n        } else {\r\n            return  $this->_master_db = $this->_db_instance($db_config, $db_config_key);\r\n        }\r\n    }\r\n\r\n    private function pdo_ping($dbconn){\r\n        try{\r\n            $dbconn->getAttribute(PDO::ATTR_SERVER_INFO);\r\n        } catch (PDOException $e) {\r\n            if(strpos($e->getMessage(), 'MySQL server has gone away')!==false){\r\n                return false;\r\n            }\r\n        }\r\n        return true;\r\n    }\r\n\r\n    private function _db_instance($db_config, $db_config_key)\r\n    {\r\n        if(!empty($GLOBALS['mysql_instances'][$db_config_key])) {\r\n            if(!$this->pdo_ping($GLOBALS['mysql_instances'][$db_config_key])){\r\n                $GLOBALS['mysql_instances'][$db_config_key] = null;\r\n            }\r\n        }\r\n        if (empty($GLOBALS['mysql_instances'][$db_config_key])) {\r\n            try {\r\n                $GLOBALS['mysql_instances'][$db_config_key] = new PDO('mysql:dbname=' . $db_config['MYSQL_DB'] . ';host=' . $db_config['MYSQL_HOST'] . ';port=' . $db_config['MYSQL_PORT'],\r\n                                                                      $db_config['MYSQL_USER'], $db_config['MYSQL_PASS'],\r\n                                                                      array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \\'' . $db_config['MYSQL_CHARSET'] . '\\''));\r\n            } catch (PDOException $e) {\r\n                Helper::log('Database Err: ' . $e->getMessage(), Helper::FATAL_ERROR);\r\n            }\r\n        }\r\n        return $GLOBALS['mysql_instances'][$db_config_key];\r\n    }\r\n\r\n    private function _wherein($sql, $inArray=array())\r\n    {\r\n        foreach ($inArray as $key => $value) {\r\n            if (!is_array($value)) {\r\n                continue;\r\n            }\r\n            $itemSql = [];\r\n            unset($inArray[$key]);\r\n            foreach ($value as $k => $item) {\r\n                $itemKey = \"{$key}_{$k}\";\r\n                array_push($itemSql, $itemKey);\r\n                $inArray[$itemKey] = $item;\r\n            }\r\n            $sql = str_replace($key, implode(',', $itemSql), $sql);\r\n        }\r\n        return [$sql, $inArray];\r\n    }\r\n\r\n    private function _where($conditions)\r\n    {\r\n        $result = array(\"_where\" => \" \", \"_bindParams\" => array());\r\n        if (empty($conditions)) {\r\n            return $result;\r\n        }\r\n        if (is_array($conditions) && !empty($conditions)) {\r\n            $sql = null;\r\n            $join = array();\r\n            if (array_values($conditions) === $conditions) {\r\n                list($sql, $conditions) = $this->_wherein($conditions[0], $conditions[1]);\r\n               // $innerJoin = $conditions[2] ?? [];\r\n            } else {\r\n                foreach ($conditions as $key => $condition) {\r\n                    $optStr = substr($key, strlen($key) - 1, 1);\r\n                    if ($optStr == '>' ) {\r\n                        $optStr2 = substr($key, strlen($key) - 1, 2);\r\n                        if($optStr2 == '<>'){\r\n                            $optStr = $optStr2;\r\n                        }\r\n                        unset($conditions[$key]);\r\n                        $key = str_replace($optStr, '', $key);\r\n                    }else if ($optStr == '=' ) {\r\n                        $optStr2 = substr($key, strlen($key) - 1, 2);\r\n                        if($optStr2 == '>=' || $optStr2 == '<='){\r\n                            $optStr = $optStr2;\r\n                        }\r\n                        unset($conditions[$key]);\r\n                        $key = str_replace($optStr, '', $key);\r\n                    } else if ($optStr == '<') {\r\n                        unset($conditions[$key]);\r\n                        $key = str_replace($optStr, '', $key);\r\n                    } else {\r\n                        $optStr = '=';\r\n                    }\r\n                    if (substr($key, 0, 1) != \":\") {\r\n                        unset($conditions[$key]);\r\n                        $conditions[\":\" . $key] = $condition;\r\n                    }\r\n                    $join[] = \"`{$key}`{$optStr} :{$key}\";\r\n                }\r\n                if (!$sql) {\r\n                    $sql = join(\" AND \", $join);\r\n                }\r\n            }\r\n            $result[\"_where\"] = \" WHERE \" . $sql;\r\n//            if(isset($innerJoin) && $innerJoin){\r\n//                $result[\"_where\"] = \" AS a INNER JOIN {$GLOBALS['prefix']}{$innerJoin[0]} AS b ON \".\r\n//                    \"a.{$innerJoin[1]} = b.{$innerJoin[2]}\".$result[\"_where\"];\r\n//            }\r\n            $result[\"_bindParams\"] = $conditions;\r\n        } else {\r\n            $result[\"_where\"] = \" WHERE \" . $conditions;\r\n            $result[\"_bindParams\"] = array();\r\n        }\r\n        return $result;\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/core/view.php",
    "content": "<?php\r\n\r\nclass View\r\n{\r\n    private $template_vals = array();\r\n\r\n    public function render($tempalte_name)\r\n    {\r\n        @ob_start();\r\n        //核心作用语句\r\n        extract($this->template_vals, EXTR_SKIP);\r\n        include $tempalte_name;\r\n        return ob_get_clean();\r\n    }\r\n\r\n    public function assign($mixed, $val = '')\r\n    {\r\n        if (is_array($mixed)) {\r\n            foreach ($mixed as $k => $v) {\r\n                if ($k != '') {\r\n                    $this->template_vals[$k] = $v;\r\n                }\r\n            }\r\n        } else {\r\n            if ($mixed != '') {\r\n                $this->template_vals[$mixed] = $val;\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "src/plugin/App.php",
    "content": "<?php\n\n//直接应用 composer 安装的名字空间\n\nclass App\n{\n    public static function redis()\n    {\n        //实例化第三方的类入口\n    }\n}"
  },
  {
    "path": "src/view/web/default.php",
    "content": "<header>\n    <h1 class=\"logo\">Welcome to ES</h1>\n    <div class=\"description\">\n        ES 是一款 极简、灵活、 高性能、扩建性强、上手快php 框架; 以“快速开发、轻松上手、高速执行”为理念，助你成为web开发的能手 ！\n    </div>\n</header>\n<footer>\n    <div class=\"author\">\n        Official website:\n        <a href=\"http://www.cnblogs.com/echosong/\">my blog</a> /\n        Contact me:\n        <a class=\"email\" href=\"mailto:313690636@qq.com\">313690636@qq.com</a>\n        <a target=\"_blank\" href=\"http://wpa.qq.com/msgrd?v=3&uin=313690636&site=qq&menu=yes\"><img border=\"0\" src=\"http://wpa.qq.com/pa?p=2:313690636:51\" alt=\"es\" title=\"es\"/></a>\n       </div>\n</footer>\n<div class=\"backdrop\"></div>"
  },
  {
    "path": "src/view/web/layout.php",
    "content": "\n<!DOCTYPE html>\n\n<html>\n<head>\n    <title>ES framework </title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <link rel=\"shortcut icon\" href=\"data:image/x-icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHS01jB0tNejdLTX33O01+10tNftdLTX7XS01+10tNftdLTX7XS01+10tNftcK/R7WOeve1gmrrtZZ687b7f6O3o/v7t6P7+7ej+/u3o/v7t6P7+7ej+/u3o/v7t6P7+7ej+/e3n/v3j5v39p+L7+zIAAAAAAAAAAAAAAAB0tNdgdLTX+3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/crLV/2ejw/9hm7r/Y5y7/7ze5//p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6P79++T8/GQAAAAAdLTXNHS01vt0tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/c7PW/2qnyP9hm7r/ZZ68/9Dt8f/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6P79++P7/Dh0tNevdLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/2uoyf9hm7r/f7HJ/+j+/f/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/5v39s3S01+90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/c7PW/2ikxP9hm7r/xOTr/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/n/v3zdLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/crLV/2KdvP+RvtL/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+j+/f90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/aqfI/2yjv//o/v3/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/9xsNL/YZu6/9fx9f/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3Oz1v9inbz/xeTs/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/2WgwP/C4ur/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/ZaDA/8/s8f/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3Oz1v9posD/5fz8/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/cK/R/5PA0//p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/9sp8f/1PDz/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/b67Q/6/V4f/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3S01/90tNf/dLTX/3Gw0v+o0N//6P79/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/014mv9NeJr/TXia/014mv9NeJr/TXia/014mv9NeJr/TXia/014mv9NeJr/TXia/014mv9NeJr/TXia/014mv9XgJ7/tM/Z/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9TfJ3/k7DD/93z9P/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9UfZ3/or7O/+L29//p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Ldpj/Zoyn/9Tr7v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/2KIo//d9PX/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9LdZX/zOPn/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/36csf/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9KdZf/rsTP/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0hzlP/D197/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/SHOT/7zP2P/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9KdJb/nLLA/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+j+/f9Md5n1THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0t2mP9ig5z/7/7+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/5vz89Ux4mrlMd5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/THeZ/0Vujf/E1Nz/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/l/Pu5TXmbQEx3mf1Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/SnWX/1p9lv/o9Pb/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6P79/d/3+EIAAAAATXiadEx3mf1Md5n/THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/SXOU/2iIn//i7/L/6v/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n//v/p//7/6f/+/+n+/f3l+/t2AAAAAAAAAAAAAAAATXmbQEx4mrlMd5n1THeZ/0x3mf9Md5n/THeZ/0x3mf9Md5n/SnSW/091kf+ftML/3Ovu//D+/v/w//7/8P/+//D//v/w//7/8P/+//D//v/w//7/8P/+//D//v/w//7/8P7+/+79/fft/f277fr7QgAAAAAAAAAA4AAAB8AAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABwAAAA+AAAAc=\" type=\"image/x-icon\" />\n    <link rel=\"stylesheet\" href=\"<?=APP_ROOT.$GLOBALS['static']?>/css/style.css\" />\n</head>\n\n<body>\n<?php include $__render_body?>\n</body>\n</html>\n"
  }
]