├── .htaccess
├── README.md
├── application
├── admin
│ ├── controller
│ │ ├── Common.php
│ │ └── Index.php
│ ├── model
│ │ └── User.php
│ └── view
│ │ └── index.html
├── common
│ ├── 404
│ │ ├── images
│ │ │ ├── 404.png
│ │ │ └── 404_bg.jpg
│ │ └── index.php
│ └── Helper.php
├── config
│ └── Config.php
├── home
│ ├── controller
│ │ ├── Common.php
│ │ └── Index.php
│ ├── model
│ │ └── User.php
│ └── view
│ │ └── default
│ │ └── index
│ │ └── index.php
└── log
│ └── php.error.log
├── composer.json
├── index.php
└── system
├── Init.php
├── common
└── Helper.php
└── core
├── Config.php
├── Database.php
├── Exception.php
├── Loader.php
├── Model.php
└── Route.php
/.htaccess:
--------------------------------------------------------------------------------
1 |
98 |
99 | 网址有错误>请检查地址是否完整或存在多余字符
100 |
101 |
102 | 网址已失效>可能页面已删除,活动已下线等
103 |
您正在寻找的页面无法找到, 105 | onclick="history.go(-1)">回到首页?
106 | 107 |'; 33 | var_dump($constArr['user']); 34 | echo ''; 35 | } -------------------------------------------------------------------------------- /application/config/Config.php: -------------------------------------------------------------------------------- 1 | [ 13 | 'system' => FRAMEWORK_PATH . 'core', 14 | 'app' => ROOT_PATH . 'application', 15 | //'test' => ROOT_PATH.'test', 16 | ], 17 | /** 18 | * 应用类库的根命名空间 19 | */ 20 | 'app_namespace' => 'app', 21 | 22 | 23 | /** 24 | * 文件(包括控制器/模型/类库等)命名均为pascal命名 25 | * 26 | * 默认命名空间及目录均为小写模式 27 | * 28 | * 设置为true即开启pascal命名法 29 | * 目录及命名空间首字母需大写 30 | * 31 | */ 32 | 'default_charset' => 'UTF-8', 33 | 'default_timezone' => 'PRC', 34 | 35 | 36 | 37 | /** 38 | * true为显示错误 39 | * 错误显示开关 40 | */ 41 | 'display_errors' => true, 42 | 43 | /** 44 | * 该项仅在(display_errors = false)条件下有效 45 | * 页面错误模板(404页面) 46 | */ 47 | 'error_template' => APP_PATH . 'common/404/index.php', 48 | /** 49 | * 该项仅在(display_errors = false)条件下有效 50 | * php错误写到日志文件 51 | */ 52 | 'error_log_file' => APP_PATH . 'log/php.error.log', 53 | 54 | 55 | 56 | /** 57 | * URL大小写配置,true为不区分大小写,false为区分 58 | * 推荐设置为区分大小写 59 | */ 60 | 'url_case' => true, 61 | /** 62 | * 仅当url_case为true时,该项有效 63 | * URL驼峰命名分隔符 64 | * 该项不能与path_separator设为相同值,避免冲突 65 | * 66 | * 当控制器或操作方法的命名是两个单词拼接时,且使用驼峰法 67 | * 下面两种URL写法是等效的, 68 | * http://servername.com/Idea-framework/index.php/home/MyClass/sayHello 69 | * http://servername.com/Idea-framework/home/my_class/say_hello 70 | */ 71 | 'url_case_separator' => '_', 72 | 73 | 74 | /** 75 | * 应用扩展目录 76 | * 该项为框架内置import()函数提供支持 77 | */ 78 | 'extend_path' => APP_PATH . 'extend/', 79 | 80 | /** 81 | * composer自动加载文件引入 82 | */ 83 | 'composer_aotuload_file' => APP_PATH . 'vendor/autoload.php', 84 | 85 | 86 | /** 87 | * 设置默认操作 88 | * 严格区分大小写,请正确设置 89 | */ 90 | 'model_dir' => 'model', //模型目录 91 | 'controller_dir' => 'controller', //控制器目录 92 | 'default_module' => 'home', //默认模块(平台、分组) 93 | 'default_controller' => 'Index', //默认控制器(该项首字母必须大写,因为控制器文件名是大驼峰命名的) 94 | 'default_action' => 'index', //默认控制器方法 95 | 96 | 97 | /** 98 | * URL路由模式选择 99 | * 1. 普通模式 如:http://servername.com/index.php?m=Home&c=User&a=login 100 | * 2. PATHINFO 如:http://servername.com/index.php/Home/User/login 101 | * 3. 当配置伪静态后,URL可以更加简洁,如http://servername.com/Home/User/login 102 | */ 103 | 'url_mode' => '1', 104 | 105 | /** 106 | * url_mode为2时该项生效 107 | * URL分割符,在开启PATHINFO模式下有效,如:http://servername.com/index.php/Home-User-login 108 | * * 该项不能与url_case_separator设为相同值,避免冲突 109 | */ 110 | 'path_separator' => '/', 111 | 112 | /** 113 | * 设置默认dsn,必须在dsn列表中存在 114 | * 115 | */ 116 | 'default_dsn' => 'master', 117 | 118 | /** 119 | * dsn列表 120 | * 更多dsn设置可以参考PHP官方手册 121 | */ 122 | 'dsn' => [ 123 | 'master' => [ 124 | 'mysql:127.0.0.1;port=3306;dbname=mydb', 125 | 'root', 126 | '123456', 127 | [ 128 | //array $driver_options 129 | PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8"', 130 | PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 131 | PDO::ATTR_PERSISTENT => false, 132 | //更多驱动选项请参考PHP手册 133 | ] 134 | ], 135 | 'mysql_slave1' => [ 136 | 'mysql:host=localhost;port=3306;dbname=test', 137 | 'root', 138 | '123456', 139 | [ 140 | //array $driver_options 141 | PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8"', 142 | PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 143 | ] 144 | ], 145 | /* 146 | 'mssql' => [ 147 | 'odbc:Driver={SQL Server};Server=localhost;Database=mydb', 148 | 'sa', 149 | '123456' 150 | ], 151 | 152 | 'oci' => ['oci:dbname=//db.example.com:1521/mydb','username','password'], 153 | 154 | 'sqlite' => 'sqlite:c:/data/sqlite.db', 155 | 156 | 'postgreSQL'=>[pgsql:host=localhost;port=5432;dbname=testdb], 157 | */ 158 | ], 159 | 160 | 161 | //这里可以添加更多自己的配置 162 | 163 | ]; -------------------------------------------------------------------------------- /application/home/controller/Common.php: -------------------------------------------------------------------------------- 1 | tpl_path = APP_PATH . 'home/view/default/'; 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /application/home/controller/Index.php: -------------------------------------------------------------------------------- 1 | 框架已成功部署,"; 18 | $ok .= "
错误内容:' . $this->getMessage() . '
'; 35 | $msg .= '异常抛出位置:' . $this->getFile() . ',第' . $this->getLine() . '行
'; 36 | $msg .= '异常追踪信息:' . $this->getTraceAsString() . '
'; 37 | echo $msg; 38 | exit; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /system/core/Loader.php: -------------------------------------------------------------------------------- 1 | 6 | * @datetime 2016/8/16 13:12 7 | * @copyright Copyright (c) 2016 8 | * @version 1.0 9 | */ 10 | namespace system; 11 | 12 | /** 13 | * Class Loader 14 | * @package system 15 | */ 16 | class Loader 17 | { 18 | 19 | private static $prefixes = []; 20 | 21 | public static function run() 22 | { 23 | self::setHeader(); 24 | //系统类映射 25 | self::getMapList(); 26 | // 注册自动加载ideaAutoload方法 27 | self::register(); 28 | self::composerload(); 29 | //实例化路由 30 | try { 31 | new Route(); 32 | } catch (Exception $e) { 33 | $e->getDetail(); 34 | } 35 | } 36 | private static function setHeader() 37 | { 38 | header("Content-type:text/html;Charset=".config('default_charset')); 39 | date_default_timezone_set(config('default_timezone')); 40 | } 41 | 42 | /** 43 | * 注册自动加载 44 | * 45 | * @return void 46 | */ 47 | public static function register() 48 | { 49 | spl_autoload_register('self::ideaAutoload'); 50 | } 51 | 52 | /** 53 | * 为命名空间前缀添加一个对应的基目录. 54 | * 55 | * @param string $prefix 命名空间前缀. 56 | * @param string $base_dir 基目录 57 | * namespace. 58 | * @param bool $prepend 前缀一致的两个base_dir,为true的在列表最开始插入 59 | * @return void 60 | */ 61 | 62 | public static function addNamespace($prefix, $base_dir, $prepend = false) 63 | { 64 | //格式化命名空间前缀,以反斜杠结束 65 | $prefix = trim($prefix, '\\') . '\\'; 66 | //格式化基目录以正斜杠结尾 67 | $base_dir = rtrim($base_dir, '/') . DIRECTORY_SEPARATOR; 68 | $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/'; 69 | //初始化命名空间前缀数组 70 | //如果前缀已存在数组中则跳过,否则存入数组 71 | if (isset(self::$prefixes[$prefix]) === false) { 72 | self::$prefixes[$prefix] = []; 73 | } 74 | 75 | if ($prepend) { 76 | //命名空间前缀相同时,后增基目录 77 | array_unshift(self::$prefixes[$prefix], $base_dir); 78 | } else { 79 | //前增 80 | array_push(self::$prefixes[$prefix], $base_dir); 81 | } 82 | } 83 | 84 | private static function getMapList() 85 | { 86 | foreach (Config::getInstance()->get('namespace_map_list') as $key => $value) { 87 | self::addNamespace($key, $value); 88 | } 89 | } 90 | 91 | /** 92 | * IdeaPHP框架自动加载方法 93 | * @param string $class_name 自动加载类/接口名 94 | * @return bool|mixed 映射文件名存在就加载,否则返回false 95 | */ 96 | private static function ideaAutoload($class_name) 97 | { 98 | // 当前命名空间前缀 99 | $prefix = $class_name; 100 | //从后面开始遍历完全合格类名中的命名空间名称,来查找映射的文件名 101 | while (false !== $pos = strrpos($prefix, '\\')) { 102 | // 命名空间前缀 103 | $prefix = substr($class_name, 0, $pos + 1); 104 | // 相对的类名 105 | $relative_class = substr($class_name, $pos + 1); 106 | //尝试加载与映射文件相对的类 107 | $mapped_file = self::loadMappedFile($prefix, $relative_class); 108 | if ($mapped_file) { 109 | return $mapped_file; 110 | } 111 | //去除前缀的反斜杠 112 | $prefix = rtrim($prefix, '\\'); 113 | } 114 | return false; 115 | } 116 | 117 | /** 118 | * 根据命名空间及相对类来加载映射文件. 119 | * 120 | * @param string $prefix 命名空间前缀 121 | * @param string $relative_class 相对类名 122 | * @return mixed Boolean 没有映射文件被加载为 false 123 | */ 124 | 125 | private static function loadMappedFile($prefix, $relative_class) 126 | { 127 | //这个命名空间前缀是否存在基本的目录? 128 | if (isset(self::$prefixes[$prefix]) === false) { 129 | return false; 130 | } 131 | 132 | $relative_class = str_replace('\\', '/', $relative_class); 133 | 134 | foreach (self::$prefixes[$prefix] as $base_dir) { 135 | $file = $base_dir . $relative_class . '.php'; 136 | // 如果映射文件存在就加载它 137 | if (self::requireFile($file)) { 138 | // 做一其他事 139 | } 140 | } 141 | return false; 142 | } 143 | 144 | /** 145 | * 如果文件存在,就从文件系统加载它 146 | * 147 | * @param string $file 加载文件 148 | * @return bool 文件存在 true 149 | */ 150 | private static function requireFile($file) 151 | { 152 | if (file_exists($file)) { 153 | include $file; 154 | return true; 155 | } 156 | return false; 157 | } 158 | private static function composerload() 159 | { 160 | //composer自动加载 161 | file_exists(config('composer_aotuload_file')) ? include config('composer_aotuload_file') : false; 162 | } 163 | } 164 | 165 | -------------------------------------------------------------------------------- /system/core/Model.php: -------------------------------------------------------------------------------- 1 | 6 | * @datetime 2016/4/22 13:12 7 | * @copyright Copyright (c) 2016 8 | * @version 1.0 9 | */ 10 | namespace system; 11 | 12 | 13 | class Model 14 | { 15 | //存储实例化的数据库操作对象 16 | protected static $db; 17 | protected static $dsn_key; 18 | 19 | /** 20 | * Model constructor. 21 | */ 22 | public function __construct() 23 | { 24 | //pdo对象 25 | self::$db = self::connect(); 26 | } 27 | 28 | /** 29 | * 选择数据源 30 | * @param $key string 数据源key 31 | * @return object pdo对象 32 | */ 33 | protected static function connect($key = null) 34 | { 35 | self::$dsn_key = isset($key) ? $key : config('default_dsn'); 36 | try { 37 | self::$db = Database::getInstance(self::$dsn_key); 38 | } catch (\PDOException $e) { 39 | echo '异常信息:' . $e->getMessage() . '
'; 41 | echo '异常信息追踪:' . $e->getTraceAsString() . '
'; 42 | exit; 43 | } 44 | return self::$db; 45 | } 46 | 47 | 48 | /** 49 | * 获得模型的单例对象 50 | * 针对所有模型 调用方法 $UserModel=self::getModel('User'); 51 | * Helper.php内的方法model(模型名,模型方法名);进行调用该类 52 | * @param string $model_name 需要得到单例对象的模型的名字,例如"User"或者"UserModel" 53 | * @return object 该模型类的单例对象 54 | */ 55 | public static function getModel($model_name) 56 | { 57 | //储存所有的模型方法 58 | static $model_lists = []; //'User'=>Object(UserModel) 59 | //判断该模型类是否已经实例化对象 60 | if (!isset($model_lists[$model_name])) { 61 | //该模型类对象不存在,则实例化 62 | $model_class_name = $model_name; 63 | $model_lists[$model_name] = new $model_class_name(); 64 | } 65 | //返回获取的模型对象 66 | return $model_lists[$model_name]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /system/core/Route.php: -------------------------------------------------------------------------------- 1 | 6 | * @datetime 2016/8/16 13:12 7 | * @copyright Copyright (c) 2016 8 | * @version 1.0 9 | */ 10 | namespace system; 11 | 12 | 13 | /** 14 | * Class Route 15 | * @package system 16 | */ 17 | class Route 18 | { 19 | private $current_module; //当前模块 20 | private $current_controller; //当前控制器 21 | private $current_action; //当前操作 22 | private $moduleDir; //模块目录 23 | private $controllerFile; //控制器文件 24 | private $controllerClassName; //控制器名 25 | private $controllerObj; 26 | 27 | /** 28 | * 加载配置信息 29 | */ 30 | public function __construct() 31 | { 32 | //设置__ROOT__值 33 | $this->setRoot(); 34 | //路由解析 35 | $this->parseUrl(); 36 | //大小写判断 37 | $this->judgmentCase(); 38 | //调用方法 39 | $this->newAction(); 40 | } 41 | 42 | /** 43 | * 判断是否SSL协议 44 | * @return boolean 45 | */ 46 | private static function isSsl() 47 | { 48 | if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) { 49 | return true; 50 | } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) { 51 | return true; 52 | } 53 | return false; 54 | } 55 | 56 | /** 57 | * 设置__ROOT__常量值 58 | */ 59 | private function setRoot() 60 | { 61 | $scheme = self::isSsl() ? 'https://' : 'http://'; 62 | if (PHP_SAPI != 'cli') { 63 | //服务器方式(URL),项目的根路径,也就是网站根目录 64 | define('__ROOT__', trim($scheme . $_SERVER['HTTP_HOST'] . $_SERVER["SCRIPT_NAME"], '/')); 65 | define('ENTRANCE', substr(__ROOT__, strrpos(__ROOT__, '/') + 1)); //入口文件名 66 | define('__APP__', rtrim($scheme . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'], ENTRANCE) . APP_NAME); 67 | } else { 68 | // 当前应用地址 69 | define('__ROOT__', ROOT_PATH . '/'); 70 | define('__APP__', rtrim(ROOT_PATH, ENTRANCE) . APP_NAME . '/'); 71 | } 72 | } 73 | 74 | /** 75 | * 分发参数 76 | */ 77 | private function parseUrl() 78 | { 79 | if (config('url_mode') == '1') { 80 | $this->current_module = isset($_GET['m']) ? $_GET['m'] : config('default_module'); 81 | //通过判断url里面是否存在c参数,如果没有则设为默认控制器 82 | $this->current_controller = isset($_GET['c']) ? $_GET['c'] : config('default_controller'); 83 | $this->current_action = isset($_GET['a']) ? $_GET['a'] : config('default_action'); 84 | } elseif (config('url_mode') == '2') { 85 | if (isset($_SERVER['PATH_INFO'])) { 86 | $paths = explode(config('path_separator'), trim($_SERVER['PATH_INFO'], '/')); 87 | $url_module = array_shift($paths); 88 | $url_controller = array_shift($paths); 89 | $url_action = array_shift($paths); 90 | //传值操作 91 | for ($i = 0; $i < count($paths); $i += 2) { 92 | if (isset($paths[$i + 1])) { 93 | $_GET[$paths[$i]] = $paths[$i + 1]; 94 | } elseif (config('display_errors') == false) { 95 | notFound(); 96 | } else { 97 | throw new Exception($paths[$i] . '未设置一个参数值'); 98 | } 99 | } 100 | } 101 | $this->current_module = !empty($url_module) ? $url_module : config('default_module'); 102 | //通过判断url里面是否存在c参数,如果没有则设为默认控制器 103 | $this->current_controller = !empty($url_controller) ? $url_controller : config('default_controller'); 104 | $this->current_action = !empty($url_action) ? $url_action : config('default_action'); 105 | } else { 106 | throw new Exception('不存在的路由参数url_mode,' . config('url_mode')); 107 | } 108 | } 109 | 110 | /** 111 | * 字符串命名风格转换 112 | * type 0 将Java风格转换为C的风格(下划线分割) 113 | * 1 将C风格转换为Java的风格(大驼峰) 114 | * 2 转型为小驼峰 115 | * @param string $name 字符串 116 | * @param boolean $type 转换类型 117 | * @return string 118 | */ 119 | private static function parseName($name, $type = 0) 120 | { 121 | if ($type == 0) { 122 | $replace = preg_replace_callback( 123 | '/' . config('url_case_separator') . '([a-zA-Z])/', 124 | function ($match) { 125 | return strtoupper($match[1]); 126 | }, 127 | $name); 128 | return ucfirst($replace); 129 | } elseif ($type == 1) { 130 | $replace = strtolower(trim(preg_replace('/[A-Z]/', config('url_case_separator') . '\0', $name), config('url_case_separator'))); 131 | return $replace; 132 | } elseif ($type == 2) { 133 | $replace = preg_replace_callback( 134 | '/' . config('url_case_separator') . '([a-zA-Z])/', 135 | function ($match) { 136 | return strtoupper($match[1]); 137 | }, 138 | $name); 139 | return $replace; 140 | } 141 | } 142 | 143 | /** 144 | * 判断大小写并定义url常量 145 | */ 146 | private function judgmentCase() 147 | { 148 | $url_case = config('url_case'); 149 | 150 | define('MODULE', $this->current_module); 151 | define('CONTROLLER', $url_case ? self::parseName($this->current_controller, 0) : $this->current_controller); 152 | define('ACTION', $url_case ? self::parseName($this->current_action, 2) : $this->current_action); 153 | 154 | if (config('url_mode') == '1') { 155 | define('__MODULE__', __ROOT__ . '?m=' . MODULE); 156 | define('__CONTROLLER__', __MODULE__ . '&c=' . CONTROLLER); 157 | define('__ACTION__', __CONTROLLER__ . '&a=' . ACTION); 158 | } elseif (config('url_mode') == '2') { 159 | define('__MODULE__', __ROOT__ . '/' . MODULE); 160 | define('__CONTROLLER__', __MODULE__ . config('path_separator') . CONTROLLER); 161 | define('__ACTION__', __CONTROLLER__ . config('path_separator') . ACTION); 162 | } 163 | 164 | $this->controllerClassName = config('app_namespace') . '\\' . MODULE . '\\' . config('controller_dir') . '\\' . CONTROLLER; 165 | //模块文件夹 166 | $this->moduleDir = APP_PATH . MODULE; 167 | 168 | //控制器文件 169 | $this->controllerFile = $this->moduleDir . '/' . config('controller_dir') . '/' . CONTROLLER . '.php'; 170 | } 171 | 172 | /** 173 | * 实例化控制器并调用操作 174 | */ 175 | private function newAction() 176 | { 177 | if (!is_dir($this->moduleDir)) { 178 | if (config('display_errors') == false) { 179 | notFound(); 180 | } else { 181 | throw new Exception('不存在的模块,' . $this->moduleDir); 182 | } 183 | } elseif (!file_exists($this->controllerFile)) { 184 | if (config('display_errors') == false) { 185 | notFound(); 186 | } else { 187 | throw new Exception('不存在的控制器,' . $this->controllerFile); 188 | } 189 | } 190 | if (class_exists($this->controllerClassName)) { 191 | $this->controllerObj = new $this->controllerClassName(); 192 | } elseif (config('display_errors') == false) { 193 | notFound(); 194 | } else { 195 | throw new Exception($this->controllerClassName . '控制器类不存在'); 196 | } 197 | 198 | if (method_exists($this->controllerClassName, ACTION)) { 199 | //开始实例方法 200 | $this->controllerObj->{ACTION}(); //可变方法 201 | } elseif (config('display_errors') == false) { 202 | notFound(); 203 | } else { 204 | throw new Exception(ACTION . '操作方法不存在'); 205 | } 206 | 207 | } 208 | } 209 | --------------------------------------------------------------------------------