├── .gitignore ├── .htaccess ├── .travis.yml ├── README.md ├── app ├── controllers │ └── ItemController.php ├── models │ └── Item.php └── views │ ├── footer.php │ ├── header.php │ └── item │ ├── add.php │ ├── delete.php │ ├── detail.php │ ├── index.php │ ├── manage.php │ └── update.php ├── composer.json ├── composer.lock ├── config └── config.php ├── fastphp ├── Fastphp.php ├── base │ ├── Controller.php │ ├── Model.php │ └── View.php └── db │ ├── Db.php │ └── Sql.php ├── index.php ├── phpunit.xml ├── static └── css │ └── main.css └── tests └── autoload.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | # 打开Rerite功能 3 | RewriteEngine On 4 | 5 | # 如果请求的是真实存在的文件或目录,直接访问 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteCond %{REQUEST_FILENAME} !-d 8 | 9 | # 如果访问的文件或目录不是真事存在,分发请求至 index.php 10 | RewriteRule . index.php 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.4 4 | 5 | before_script: 6 | - composer install 7 | 8 | script: 9 | - phpunit -c phpunit.xml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastPHP 2 | 3 | [![Build Status](https://travis-ci.org/yeszao/fastphp.svg?branch=master)](https://travis-ci.org/yeszao/fastphp) 4 | [![Latest Stable Version](https://poser.pugx.org/yeszao/fastphp/v/stable)](https://packagist.org/packages/yeszao/fastphp) 5 | [![Total Downloads](https://poser.pugx.org/yeszao/fastphp/downloads)](https://packagist.org/packages/yeszao/fastphp) 6 | [![Latest Unstable Version](https://poser.pugx.org/yeszao/fastphp/v/unstable)](https://packagist.org/packages/yeszao/fastphp) 7 | [![License](https://poser.pugx.org/yeszao/fastphp/license)](https://packagist.org/packages/yeszao/fastphp) 8 | 9 | ## 简述 10 | 11 | **fastphp**是一款简单的PHP MVC框架,目的是方便学习《手把手编写自己的PHP MVC框架》教程的同学下载源代码,详细介绍请参考网站:http://www.awaimai.com/128.html 。 12 | 13 | 要求: 14 | 15 | * PHP 5.4.0+ 16 | 17 | ## 目录说明 18 | 19 | ``` 20 | project 根目录 21 | ├─app 应用目录 22 | │ ├─controllers 控制器目录 23 | │ ├─models 模块目录 24 | │ ├─views 视图目录 25 | ├─config 配置文件目录 26 | ├─fastphp 框架核心目录 27 | ├─static 静态文件目录 28 | ├─index.php 入口文件 29 | ``` 30 | 31 | ## 使用 32 | 33 | ### 1.安装 34 | 主要介绍通过composer和git两种安装方法,选择其一即可。 35 | 36 | **方法1**:Composer安装(推荐) 37 | ``` 38 | composer create-project yeszao/fastphp project --no-dev 39 | ``` 40 | 其中,`--no-dev`表示不安装-dev依赖包(PHPUnit)。 41 | 42 | **方法2**:Github安装: 43 | ``` 44 | git clone https://github.com/yeszao/fastphp.git project 45 | ``` 46 | > 说明:这两个命令都会创建并将代码安装到`project`目录。 47 | 48 | ### 2. 创建数据库 49 | 50 | 在数据库中创建名为 project 的数据库,并插入两条记录,命令: 51 | 52 | ``` 53 | CREATE DATABASE `project` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 54 | USE `project`; 55 | 56 | CREATE TABLE `item` ( 57 | `id` int(11) NOT NULL auto_increment, 58 | `item_name` varchar(255) NOT NULL, 59 | PRIMARY KEY (`id`) 60 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 61 | 62 | INSERT INTO `item` VALUES(1, 'Hello World.'); 63 | INSERT INTO `item` VALUES(2, 'Lets go!'); 64 | ``` 65 | 66 | ### 3.修改数据库配置文件 67 | 68 | 打开配置文件 config/config.php ,使之与自己的数据库匹配 69 | 70 | ``` 71 | $config['db']['host'] = 'localhost'; 72 | $config['db']['username'] = 'root'; 73 | $config['db']['password'] = '123456'; 74 | $config['db']['dbname'] = 'project'; 75 | ``` 76 | 77 | ### 4.配置Nginx或Apache 78 | 在Apache或Nginx中创建一个站点,把 project 设置为站点根目录(入口文件 index.php 所在的目录)。 79 | 80 | 然后设置单一入口, Apache服务器配置: 81 | ``` 82 | 83 | # 打开Rerite功能 84 | RewriteEngine On 85 | 86 | # 如果请求的是真实存在的文件或目录,直接访问 87 | RewriteCond %{REQUEST_FILENAME} !-f 88 | RewriteCond %{REQUEST_FILENAME} !-d 89 | 90 | # 如果访问的文件或目录不是真事存在,分发请求至 index.php 91 | RewriteRule . index.php 92 | 93 | ``` 94 | Nginx服务器配置: 95 | ``` 96 | location / { 97 |    # 重新向所有非真实存在的请求到index.php 98 | try_files $uri $uri/ /index.php$args; 99 | } 100 | ``` 101 | 102 | ### 5.测试访问 103 | 104 | 然后访问站点域名:http://localhost/ 就可以了。 105 | -------------------------------------------------------------------------------- /app/controllers/ItemController.php: -------------------------------------------------------------------------------- 1 | search($keyword); 16 | } else { 17 | // 查询所有内容,并按倒序排列输出 18 | // where()方法可不传入参数,或者省略 19 | $items = (new Item)->where()->order(['id DESC'])->fetchAll(); 20 | } 21 | 22 | $this->assign('title', '全部条目'); 23 | $this->assign('keyword', $keyword); 24 | $this->assign('items', $items); 25 | $this->render(); 26 | } 27 | 28 | // 查看单条记录详情 29 | public function detail($id) 30 | { 31 | // 通过?占位符传入$id参数 32 | $item = (new Item())->where(["id = ?"], [$id])->fetch(); 33 | 34 | $this->assign('title', '条目详情'); 35 | $this->assign('item', $item); 36 | $this->render(); 37 | } 38 | 39 | // 添加记录,测试框架DB记录创建(Create) 40 | public function add() 41 | { 42 | $data['item_name'] = $_POST['value']; 43 | $count = (new Item)->add($data); 44 | 45 | $this->assign('title', '添加成功'); 46 | $this->assign('count', $count); 47 | $this->render(); 48 | } 49 | 50 | // 操作管理 51 | public function manage($id = 0) 52 | { 53 | $item = array(); 54 | if ($id) { 55 | // 通过名称占位符传入参数 56 | $item = (new Item())->where(["id = :id"], [':id' => $id])->fetch(); 57 | } 58 | 59 | $this->assign('title', '管理条目'); 60 | $this->assign('item', $item); 61 | $this->render(); 62 | } 63 | 64 | // 更新记录,测试框架DB记录更新(Update) 65 | public function update() 66 | { 67 | $data = array('id' => $_POST['id'], 'item_name' => $_POST['value']); 68 | $count = (new Item)->where(['id = :id'], [':id' => $data['id']])->update($data); 69 | 70 | $this->assign('title', '修改成功'); 71 | $this->assign('count', $count); 72 | $this->render(); 73 | } 74 | 75 | // 删除记录,测试框架DB记录删除(Delete) 76 | public function delete($id = null) 77 | { 78 | $count = (new Item)->delete($id); 79 | 80 | $this->assign('title', '删除成功'); 81 | $this->assign('count', $count); 82 | $this->render(); 83 | } 84 | } -------------------------------------------------------------------------------- /app/models/Item.php: -------------------------------------------------------------------------------- 1 | table` where `item_name` like :keyword"; 30 | $sth = Db::pdo()->prepare($sql); 31 | $sth = $this->formatParam($sth, [':keyword' => "%$keyword%"]); 32 | $sth->execute(); 33 | 34 | return $sth->fetchAll(); 35 | } 36 | } -------------------------------------------------------------------------------- /app/views/footer.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/views/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <?php echo $title ?> 5 | 6 | 7 | 8 |

-------------------------------------------------------------------------------- /app/views/item/add.php: -------------------------------------------------------------------------------- 1 | 成功添加条记录,点击返回 -------------------------------------------------------------------------------- /app/views/item/delete.php: -------------------------------------------------------------------------------- 1 | 成功删除项,点击返回 -------------------------------------------------------------------------------- /app/views/item/detail.php: -------------------------------------------------------------------------------- 1 | ID:
2 | Name: 3 | 4 |
5 |
6 | 返回 -------------------------------------------------------------------------------- /app/views/item/index.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 |

新建

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 26 | 27 | 28 |
ID内容操作
18 | 19 | 20 | 21 | 23 | 编辑 24 | 删除 25 |
29 | -------------------------------------------------------------------------------- /app/views/item/manage.php: -------------------------------------------------------------------------------- 1 |
2 | action="/item/update/" 3 | 4 | action="/item/add" 5 | 6 | method="post"> 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 返回 -------------------------------------------------------------------------------- /app/views/item/update.php: -------------------------------------------------------------------------------- 1 | 成功修改项,点击返回 -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yeszao/fastphp", 3 | "description": "Simple and lightweight PHP framework", 4 | "type": "project", 5 | "keywords": [ 6 | "framework", 7 | "fastphp", 8 | "mvc" 9 | ], 10 | "homepage": "http://www.awaimai.com", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "gary", 15 | "email": "galley.meng@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=5.4.0" 20 | }, 21 | "require-dev": { 22 | "phpunit/phpunit": "~4.8.0" 23 | }, 24 | "config": { 25 | "preferred-install": "dist", 26 | "platform": { 27 | "php": "5.4" 28 | } 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "app\\": "app" 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "8f3ef4b5386a8be86fdc144c48ab6480", 8 | "content-hash": "512a0349566ca8e9ac5719a4aed5b7f3", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "1.0.5", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://files.phpcomposer.com/files/doctrine/instantiator/8e884e78f9f0eb1329e445619e04456e64d8051d.zip", 22 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "~2.0" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2015-06-14 21:17:01" 64 | }, 65 | { 66 | "name": "phpdocumentor/reflection-docblock", 67 | "version": "2.0.5", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 71 | "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://files.phpcomposer.com/files/phpDocumentor/ReflectionDocBlock/e6a969a640b00d8daa3c66518b0405fb41ae0c4b.zip", 76 | "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": ">=5.3.3" 81 | }, 82 | "require-dev": { 83 | "phpunit/phpunit": "~4.0" 84 | }, 85 | "suggest": { 86 | "dflydev/markdown": "~1.0", 87 | "erusev/parsedown": "~1.0" 88 | }, 89 | "type": "library", 90 | "extra": { 91 | "branch-alias": { 92 | "dev-master": "2.0.x-dev" 93 | } 94 | }, 95 | "autoload": { 96 | "psr-0": { 97 | "phpDocumentor": [ 98 | "src/" 99 | ] 100 | } 101 | }, 102 | "notification-url": "https://packagist.org/downloads/", 103 | "license": [ 104 | "MIT" 105 | ], 106 | "authors": [ 107 | { 108 | "name": "Mike van Riel", 109 | "email": "mike.vanriel@naenius.com" 110 | } 111 | ], 112 | "time": "2016-01-25 08:17:30" 113 | }, 114 | { 115 | "name": "phpspec/prophecy", 116 | "version": "1.7.3", 117 | "source": { 118 | "type": "git", 119 | "url": "https://github.com/phpspec/prophecy.git", 120 | "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" 121 | }, 122 | "dist": { 123 | "type": "zip", 124 | "url": "https://files.phpcomposer.com/files/phpspec/prophecy/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf.zip", 125 | "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", 126 | "shasum": "" 127 | }, 128 | "require": { 129 | "doctrine/instantiator": "^1.0.2", 130 | "php": "^5.3|^7.0", 131 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 132 | "sebastian/comparator": "^1.1|^2.0", 133 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 134 | }, 135 | "require-dev": { 136 | "phpspec/phpspec": "^2.5|^3.2", 137 | "phpunit/phpunit": "^4.8.35 || ^5.7" 138 | }, 139 | "type": "library", 140 | "extra": { 141 | "branch-alias": { 142 | "dev-master": "1.7.x-dev" 143 | } 144 | }, 145 | "autoload": { 146 | "psr-0": { 147 | "Prophecy\\": "src/" 148 | } 149 | }, 150 | "notification-url": "https://packagist.org/downloads/", 151 | "license": [ 152 | "MIT" 153 | ], 154 | "authors": [ 155 | { 156 | "name": "Konstantin Kudryashov", 157 | "email": "ever.zet@gmail.com", 158 | "homepage": "http://everzet.com" 159 | }, 160 | { 161 | "name": "Marcello Duarte", 162 | "email": "marcello.duarte@gmail.com" 163 | } 164 | ], 165 | "description": "Highly opinionated mocking framework for PHP 5.3+", 166 | "homepage": "https://github.com/phpspec/prophecy", 167 | "keywords": [ 168 | "Double", 169 | "Dummy", 170 | "fake", 171 | "mock", 172 | "spy", 173 | "stub" 174 | ], 175 | "time": "2017-11-24 13:59:53" 176 | }, 177 | { 178 | "name": "phpunit/php-code-coverage", 179 | "version": "2.2.4", 180 | "source": { 181 | "type": "git", 182 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 183 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 184 | }, 185 | "dist": { 186 | "type": "zip", 187 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/php-code-coverage/eabf68b476ac7d0f73793aada060f1c1a9bf8979.zip", 188 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 189 | "shasum": "" 190 | }, 191 | "require": { 192 | "php": ">=5.3.3", 193 | "phpunit/php-file-iterator": "~1.3", 194 | "phpunit/php-text-template": "~1.2", 195 | "phpunit/php-token-stream": "~1.3", 196 | "sebastian/environment": "^1.3.2", 197 | "sebastian/version": "~1.0" 198 | }, 199 | "require-dev": { 200 | "ext-xdebug": ">=2.1.4", 201 | "phpunit/phpunit": "~4" 202 | }, 203 | "suggest": { 204 | "ext-dom": "*", 205 | "ext-xdebug": ">=2.2.1", 206 | "ext-xmlwriter": "*" 207 | }, 208 | "type": "library", 209 | "extra": { 210 | "branch-alias": { 211 | "dev-master": "2.2.x-dev" 212 | } 213 | }, 214 | "autoload": { 215 | "classmap": [ 216 | "src/" 217 | ] 218 | }, 219 | "notification-url": "https://packagist.org/downloads/", 220 | "license": [ 221 | "BSD-3-Clause" 222 | ], 223 | "authors": [ 224 | { 225 | "name": "Sebastian Bergmann", 226 | "email": "sb@sebastian-bergmann.de", 227 | "role": "lead" 228 | } 229 | ], 230 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 231 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 232 | "keywords": [ 233 | "coverage", 234 | "testing", 235 | "xunit" 236 | ], 237 | "time": "2015-10-06 15:47:00" 238 | }, 239 | { 240 | "name": "phpunit/php-file-iterator", 241 | "version": "1.4.5", 242 | "source": { 243 | "type": "git", 244 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 245 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 246 | }, 247 | "dist": { 248 | "type": "zip", 249 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/php-file-iterator/730b01bc3e867237eaac355e06a36b85dd93a8b4.zip", 250 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 251 | "shasum": "" 252 | }, 253 | "require": { 254 | "php": ">=5.3.3" 255 | }, 256 | "type": "library", 257 | "extra": { 258 | "branch-alias": { 259 | "dev-master": "1.4.x-dev" 260 | } 261 | }, 262 | "autoload": { 263 | "classmap": [ 264 | "src/" 265 | ] 266 | }, 267 | "notification-url": "https://packagist.org/downloads/", 268 | "license": [ 269 | "BSD-3-Clause" 270 | ], 271 | "authors": [ 272 | { 273 | "name": "Sebastian Bergmann", 274 | "email": "sb@sebastian-bergmann.de", 275 | "role": "lead" 276 | } 277 | ], 278 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 279 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 280 | "keywords": [ 281 | "filesystem", 282 | "iterator" 283 | ], 284 | "time": "2017-11-27 13:52:08" 285 | }, 286 | { 287 | "name": "phpunit/php-text-template", 288 | "version": "1.2.1", 289 | "source": { 290 | "type": "git", 291 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 292 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 293 | }, 294 | "dist": { 295 | "type": "zip", 296 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/php-text-template/31f8b717e51d9a2afca6c9f046f5d69fc27c8686.zip", 297 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 298 | "shasum": "" 299 | }, 300 | "require": { 301 | "php": ">=5.3.3" 302 | }, 303 | "type": "library", 304 | "autoload": { 305 | "classmap": [ 306 | "src/" 307 | ] 308 | }, 309 | "notification-url": "https://packagist.org/downloads/", 310 | "license": [ 311 | "BSD-3-Clause" 312 | ], 313 | "authors": [ 314 | { 315 | "name": "Sebastian Bergmann", 316 | "email": "sebastian@phpunit.de", 317 | "role": "lead" 318 | } 319 | ], 320 | "description": "Simple template engine.", 321 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 322 | "keywords": [ 323 | "template" 324 | ], 325 | "time": "2015-06-21 13:50:34" 326 | }, 327 | { 328 | "name": "phpunit/php-timer", 329 | "version": "1.0.9", 330 | "source": { 331 | "type": "git", 332 | "url": "https://github.com/sebastianbergmann/php-timer.git", 333 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 334 | }, 335 | "dist": { 336 | "type": "zip", 337 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/php-timer/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f.zip", 338 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 339 | "shasum": "" 340 | }, 341 | "require": { 342 | "php": "^5.3.3 || ^7.0" 343 | }, 344 | "require-dev": { 345 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 346 | }, 347 | "type": "library", 348 | "extra": { 349 | "branch-alias": { 350 | "dev-master": "1.0-dev" 351 | } 352 | }, 353 | "autoload": { 354 | "classmap": [ 355 | "src/" 356 | ] 357 | }, 358 | "notification-url": "https://packagist.org/downloads/", 359 | "license": [ 360 | "BSD-3-Clause" 361 | ], 362 | "authors": [ 363 | { 364 | "name": "Sebastian Bergmann", 365 | "email": "sb@sebastian-bergmann.de", 366 | "role": "lead" 367 | } 368 | ], 369 | "description": "Utility class for timing", 370 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 371 | "keywords": [ 372 | "timer" 373 | ], 374 | "time": "2017-02-26 11:10:40" 375 | }, 376 | { 377 | "name": "phpunit/php-token-stream", 378 | "version": "1.4.12", 379 | "source": { 380 | "type": "git", 381 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 382 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 383 | }, 384 | "dist": { 385 | "type": "zip", 386 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/php-token-stream/1ce90ba27c42e4e44e6d8458241466380b51fa16.zip", 387 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 388 | "shasum": "" 389 | }, 390 | "require": { 391 | "ext-tokenizer": "*", 392 | "php": ">=5.3.3" 393 | }, 394 | "require-dev": { 395 | "phpunit/phpunit": "~4.2" 396 | }, 397 | "type": "library", 398 | "extra": { 399 | "branch-alias": { 400 | "dev-master": "1.4-dev" 401 | } 402 | }, 403 | "autoload": { 404 | "classmap": [ 405 | "src/" 406 | ] 407 | }, 408 | "notification-url": "https://packagist.org/downloads/", 409 | "license": [ 410 | "BSD-3-Clause" 411 | ], 412 | "authors": [ 413 | { 414 | "name": "Sebastian Bergmann", 415 | "email": "sebastian@phpunit.de" 416 | } 417 | ], 418 | "description": "Wrapper around PHP's tokenizer extension.", 419 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 420 | "keywords": [ 421 | "tokenizer" 422 | ], 423 | "time": "2017-12-04 08:55:13" 424 | }, 425 | { 426 | "name": "phpunit/phpunit", 427 | "version": "4.8.36", 428 | "source": { 429 | "type": "git", 430 | "url": "https://github.com/sebastianbergmann/phpunit.git", 431 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" 432 | }, 433 | "dist": { 434 | "type": "zip", 435 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/phpunit/46023de9a91eec7dfb06cc56cb4e260017298517.zip", 436 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", 437 | "shasum": "" 438 | }, 439 | "require": { 440 | "ext-dom": "*", 441 | "ext-json": "*", 442 | "ext-pcre": "*", 443 | "ext-reflection": "*", 444 | "ext-spl": "*", 445 | "php": ">=5.3.3", 446 | "phpspec/prophecy": "^1.3.1", 447 | "phpunit/php-code-coverage": "~2.1", 448 | "phpunit/php-file-iterator": "~1.4", 449 | "phpunit/php-text-template": "~1.2", 450 | "phpunit/php-timer": "^1.0.6", 451 | "phpunit/phpunit-mock-objects": "~2.3", 452 | "sebastian/comparator": "~1.2.2", 453 | "sebastian/diff": "~1.2", 454 | "sebastian/environment": "~1.3", 455 | "sebastian/exporter": "~1.2", 456 | "sebastian/global-state": "~1.0", 457 | "sebastian/version": "~1.0", 458 | "symfony/yaml": "~2.1|~3.0" 459 | }, 460 | "suggest": { 461 | "phpunit/php-invoker": "~1.1" 462 | }, 463 | "bin": [ 464 | "phpunit" 465 | ], 466 | "type": "library", 467 | "extra": { 468 | "branch-alias": { 469 | "dev-master": "4.8.x-dev" 470 | } 471 | }, 472 | "autoload": { 473 | "classmap": [ 474 | "src/" 475 | ] 476 | }, 477 | "notification-url": "https://packagist.org/downloads/", 478 | "license": [ 479 | "BSD-3-Clause" 480 | ], 481 | "authors": [ 482 | { 483 | "name": "Sebastian Bergmann", 484 | "email": "sebastian@phpunit.de", 485 | "role": "lead" 486 | } 487 | ], 488 | "description": "The PHP Unit Testing framework.", 489 | "homepage": "https://phpunit.de/", 490 | "keywords": [ 491 | "phpunit", 492 | "testing", 493 | "xunit" 494 | ], 495 | "time": "2017-06-21 08:07:12" 496 | }, 497 | { 498 | "name": "phpunit/phpunit-mock-objects", 499 | "version": "2.3.8", 500 | "source": { 501 | "type": "git", 502 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 503 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 504 | }, 505 | "dist": { 506 | "type": "zip", 507 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/phpunit-mock-objects/ac8e7a3db35738d56ee9a76e78a4e03d97628983.zip", 508 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 509 | "shasum": "" 510 | }, 511 | "require": { 512 | "doctrine/instantiator": "^1.0.2", 513 | "php": ">=5.3.3", 514 | "phpunit/php-text-template": "~1.2", 515 | "sebastian/exporter": "~1.2" 516 | }, 517 | "require-dev": { 518 | "phpunit/phpunit": "~4.4" 519 | }, 520 | "suggest": { 521 | "ext-soap": "*" 522 | }, 523 | "type": "library", 524 | "extra": { 525 | "branch-alias": { 526 | "dev-master": "2.3.x-dev" 527 | } 528 | }, 529 | "autoload": { 530 | "classmap": [ 531 | "src/" 532 | ] 533 | }, 534 | "notification-url": "https://packagist.org/downloads/", 535 | "license": [ 536 | "BSD-3-Clause" 537 | ], 538 | "authors": [ 539 | { 540 | "name": "Sebastian Bergmann", 541 | "email": "sb@sebastian-bergmann.de", 542 | "role": "lead" 543 | } 544 | ], 545 | "description": "Mock Object library for PHPUnit", 546 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 547 | "keywords": [ 548 | "mock", 549 | "xunit" 550 | ], 551 | "time": "2015-10-02 06:51:40" 552 | }, 553 | { 554 | "name": "sebastian/comparator", 555 | "version": "1.2.4", 556 | "source": { 557 | "type": "git", 558 | "url": "https://github.com/sebastianbergmann/comparator.git", 559 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 560 | }, 561 | "dist": { 562 | "type": "zip", 563 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/comparator/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be.zip", 564 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 565 | "shasum": "" 566 | }, 567 | "require": { 568 | "php": ">=5.3.3", 569 | "sebastian/diff": "~1.2", 570 | "sebastian/exporter": "~1.2 || ~2.0" 571 | }, 572 | "require-dev": { 573 | "phpunit/phpunit": "~4.4" 574 | }, 575 | "type": "library", 576 | "extra": { 577 | "branch-alias": { 578 | "dev-master": "1.2.x-dev" 579 | } 580 | }, 581 | "autoload": { 582 | "classmap": [ 583 | "src/" 584 | ] 585 | }, 586 | "notification-url": "https://packagist.org/downloads/", 587 | "license": [ 588 | "BSD-3-Clause" 589 | ], 590 | "authors": [ 591 | { 592 | "name": "Jeff Welch", 593 | "email": "whatthejeff@gmail.com" 594 | }, 595 | { 596 | "name": "Volker Dusch", 597 | "email": "github@wallbash.com" 598 | }, 599 | { 600 | "name": "Bernhard Schussek", 601 | "email": "bschussek@2bepublished.at" 602 | }, 603 | { 604 | "name": "Sebastian Bergmann", 605 | "email": "sebastian@phpunit.de" 606 | } 607 | ], 608 | "description": "Provides the functionality to compare PHP values for equality", 609 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 610 | "keywords": [ 611 | "comparator", 612 | "compare", 613 | "equality" 614 | ], 615 | "time": "2017-01-29 09:50:25" 616 | }, 617 | { 618 | "name": "sebastian/diff", 619 | "version": "1.4.3", 620 | "source": { 621 | "type": "git", 622 | "url": "https://github.com/sebastianbergmann/diff.git", 623 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 624 | }, 625 | "dist": { 626 | "type": "zip", 627 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/diff/7f066a26a962dbe58ddea9f72a4e82874a3975a4.zip", 628 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 629 | "shasum": "" 630 | }, 631 | "require": { 632 | "php": "^5.3.3 || ^7.0" 633 | }, 634 | "require-dev": { 635 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 636 | }, 637 | "type": "library", 638 | "extra": { 639 | "branch-alias": { 640 | "dev-master": "1.4-dev" 641 | } 642 | }, 643 | "autoload": { 644 | "classmap": [ 645 | "src/" 646 | ] 647 | }, 648 | "notification-url": "https://packagist.org/downloads/", 649 | "license": [ 650 | "BSD-3-Clause" 651 | ], 652 | "authors": [ 653 | { 654 | "name": "Kore Nordmann", 655 | "email": "mail@kore-nordmann.de" 656 | }, 657 | { 658 | "name": "Sebastian Bergmann", 659 | "email": "sebastian@phpunit.de" 660 | } 661 | ], 662 | "description": "Diff implementation", 663 | "homepage": "https://github.com/sebastianbergmann/diff", 664 | "keywords": [ 665 | "diff" 666 | ], 667 | "time": "2017-05-22 07:24:03" 668 | }, 669 | { 670 | "name": "sebastian/environment", 671 | "version": "1.3.8", 672 | "source": { 673 | "type": "git", 674 | "url": "https://github.com/sebastianbergmann/environment.git", 675 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" 676 | }, 677 | "dist": { 678 | "type": "zip", 679 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/environment/be2c607e43ce4c89ecd60e75c6a85c126e754aea.zip", 680 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", 681 | "shasum": "" 682 | }, 683 | "require": { 684 | "php": "^5.3.3 || ^7.0" 685 | }, 686 | "require-dev": { 687 | "phpunit/phpunit": "^4.8 || ^5.0" 688 | }, 689 | "type": "library", 690 | "extra": { 691 | "branch-alias": { 692 | "dev-master": "1.3.x-dev" 693 | } 694 | }, 695 | "autoload": { 696 | "classmap": [ 697 | "src/" 698 | ] 699 | }, 700 | "notification-url": "https://packagist.org/downloads/", 701 | "license": [ 702 | "BSD-3-Clause" 703 | ], 704 | "authors": [ 705 | { 706 | "name": "Sebastian Bergmann", 707 | "email": "sebastian@phpunit.de" 708 | } 709 | ], 710 | "description": "Provides functionality to handle HHVM/PHP environments", 711 | "homepage": "http://www.github.com/sebastianbergmann/environment", 712 | "keywords": [ 713 | "Xdebug", 714 | "environment", 715 | "hhvm" 716 | ], 717 | "time": "2016-08-18 05:49:44" 718 | }, 719 | { 720 | "name": "sebastian/exporter", 721 | "version": "1.2.2", 722 | "source": { 723 | "type": "git", 724 | "url": "https://github.com/sebastianbergmann/exporter.git", 725 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 726 | }, 727 | "dist": { 728 | "type": "zip", 729 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/exporter/42c4c2eec485ee3e159ec9884f95b431287edde4.zip", 730 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 731 | "shasum": "" 732 | }, 733 | "require": { 734 | "php": ">=5.3.3", 735 | "sebastian/recursion-context": "~1.0" 736 | }, 737 | "require-dev": { 738 | "ext-mbstring": "*", 739 | "phpunit/phpunit": "~4.4" 740 | }, 741 | "type": "library", 742 | "extra": { 743 | "branch-alias": { 744 | "dev-master": "1.3.x-dev" 745 | } 746 | }, 747 | "autoload": { 748 | "classmap": [ 749 | "src/" 750 | ] 751 | }, 752 | "notification-url": "https://packagist.org/downloads/", 753 | "license": [ 754 | "BSD-3-Clause" 755 | ], 756 | "authors": [ 757 | { 758 | "name": "Jeff Welch", 759 | "email": "whatthejeff@gmail.com" 760 | }, 761 | { 762 | "name": "Volker Dusch", 763 | "email": "github@wallbash.com" 764 | }, 765 | { 766 | "name": "Bernhard Schussek", 767 | "email": "bschussek@2bepublished.at" 768 | }, 769 | { 770 | "name": "Sebastian Bergmann", 771 | "email": "sebastian@phpunit.de" 772 | }, 773 | { 774 | "name": "Adam Harvey", 775 | "email": "aharvey@php.net" 776 | } 777 | ], 778 | "description": "Provides the functionality to export PHP variables for visualization", 779 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 780 | "keywords": [ 781 | "export", 782 | "exporter" 783 | ], 784 | "time": "2016-06-17 09:04:28" 785 | }, 786 | { 787 | "name": "sebastian/global-state", 788 | "version": "1.1.1", 789 | "source": { 790 | "type": "git", 791 | "url": "https://github.com/sebastianbergmann/global-state.git", 792 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 793 | }, 794 | "dist": { 795 | "type": "zip", 796 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/global-state/bc37d50fea7d017d3d340f230811c9f1d7280af4.zip", 797 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 798 | "shasum": "" 799 | }, 800 | "require": { 801 | "php": ">=5.3.3" 802 | }, 803 | "require-dev": { 804 | "phpunit/phpunit": "~4.2" 805 | }, 806 | "suggest": { 807 | "ext-uopz": "*" 808 | }, 809 | "type": "library", 810 | "extra": { 811 | "branch-alias": { 812 | "dev-master": "1.0-dev" 813 | } 814 | }, 815 | "autoload": { 816 | "classmap": [ 817 | "src/" 818 | ] 819 | }, 820 | "notification-url": "https://packagist.org/downloads/", 821 | "license": [ 822 | "BSD-3-Clause" 823 | ], 824 | "authors": [ 825 | { 826 | "name": "Sebastian Bergmann", 827 | "email": "sebastian@phpunit.de" 828 | } 829 | ], 830 | "description": "Snapshotting of global state", 831 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 832 | "keywords": [ 833 | "global state" 834 | ], 835 | "time": "2015-10-12 03:26:01" 836 | }, 837 | { 838 | "name": "sebastian/recursion-context", 839 | "version": "1.0.5", 840 | "source": { 841 | "type": "git", 842 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 843 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 844 | }, 845 | "dist": { 846 | "type": "zip", 847 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/recursion-context/b19cc3298482a335a95f3016d2f8a6950f0fbcd7.zip", 848 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 849 | "shasum": "" 850 | }, 851 | "require": { 852 | "php": ">=5.3.3" 853 | }, 854 | "require-dev": { 855 | "phpunit/phpunit": "~4.4" 856 | }, 857 | "type": "library", 858 | "extra": { 859 | "branch-alias": { 860 | "dev-master": "1.0.x-dev" 861 | } 862 | }, 863 | "autoload": { 864 | "classmap": [ 865 | "src/" 866 | ] 867 | }, 868 | "notification-url": "https://packagist.org/downloads/", 869 | "license": [ 870 | "BSD-3-Clause" 871 | ], 872 | "authors": [ 873 | { 874 | "name": "Jeff Welch", 875 | "email": "whatthejeff@gmail.com" 876 | }, 877 | { 878 | "name": "Sebastian Bergmann", 879 | "email": "sebastian@phpunit.de" 880 | }, 881 | { 882 | "name": "Adam Harvey", 883 | "email": "aharvey@php.net" 884 | } 885 | ], 886 | "description": "Provides functionality to recursively process PHP variables", 887 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 888 | "time": "2016-10-03 07:41:43" 889 | }, 890 | { 891 | "name": "sebastian/version", 892 | "version": "1.0.6", 893 | "source": { 894 | "type": "git", 895 | "url": "https://github.com/sebastianbergmann/version.git", 896 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 897 | }, 898 | "dist": { 899 | "type": "zip", 900 | "url": "https://files.phpcomposer.com/files/sebastianbergmann/version/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6.zip", 901 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 902 | "shasum": "" 903 | }, 904 | "type": "library", 905 | "autoload": { 906 | "classmap": [ 907 | "src/" 908 | ] 909 | }, 910 | "notification-url": "https://packagist.org/downloads/", 911 | "license": [ 912 | "BSD-3-Clause" 913 | ], 914 | "authors": [ 915 | { 916 | "name": "Sebastian Bergmann", 917 | "email": "sebastian@phpunit.de", 918 | "role": "lead" 919 | } 920 | ], 921 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 922 | "homepage": "https://github.com/sebastianbergmann/version", 923 | "time": "2015-06-21 13:59:46" 924 | }, 925 | { 926 | "name": "symfony/yaml", 927 | "version": "v2.8.32", 928 | "source": { 929 | "type": "git", 930 | "url": "https://github.com/symfony/yaml.git", 931 | "reference": "968ef42161e4bc04200119da473077f9e7015128" 932 | }, 933 | "dist": { 934 | "type": "zip", 935 | "url": "https://files.phpcomposer.com/files/symfony/yaml/968ef42161e4bc04200119da473077f9e7015128.zip", 936 | "reference": "968ef42161e4bc04200119da473077f9e7015128", 937 | "shasum": "" 938 | }, 939 | "require": { 940 | "php": ">=5.3.9" 941 | }, 942 | "type": "library", 943 | "extra": { 944 | "branch-alias": { 945 | "dev-master": "2.8-dev" 946 | } 947 | }, 948 | "autoload": { 949 | "psr-4": { 950 | "Symfony\\Component\\Yaml\\": "" 951 | }, 952 | "exclude-from-classmap": [ 953 | "/Tests/" 954 | ] 955 | }, 956 | "notification-url": "https://packagist.org/downloads/", 957 | "license": [ 958 | "MIT" 959 | ], 960 | "authors": [ 961 | { 962 | "name": "Fabien Potencier", 963 | "email": "fabien@symfony.com" 964 | }, 965 | { 966 | "name": "Symfony Community", 967 | "homepage": "https://symfony.com/contributors" 968 | } 969 | ], 970 | "description": "Symfony Yaml Component", 971 | "homepage": "https://symfony.com", 972 | "time": "2017-11-29 09:33:18" 973 | } 974 | ], 975 | "aliases": [], 976 | "minimum-stability": "stable", 977 | "stability-flags": [], 978 | "prefer-stable": false, 979 | "prefer-lowest": false, 980 | "platform": { 981 | "php": ">=5.4.0" 982 | }, 983 | "platform-dev": [], 984 | "platform-overrides": { 985 | "php": "5.4" 986 | } 987 | } 988 | -------------------------------------------------------------------------------- /config/config.php: -------------------------------------------------------------------------------- 1 | config = $config; 19 | } 20 | 21 | // 运行程序 22 | public function run() 23 | { 24 | spl_autoload_register(array($this, 'loadClass')); 25 | $this->setReporting(); 26 | $this->removeMagicQuotes(); 27 | $this->unregisterGlobals(); 28 | $this->setDbConfig(); 29 | $this->route(); 30 | } 31 | 32 | // 路由处理 33 | public function route() 34 | { 35 | $controllerName = $this->config['defaultController']; 36 | $actionName = $this->config['defaultAction']; 37 | $param = array(); 38 | 39 | $url = $_SERVER['REQUEST_URI']; 40 | // 清除?之后的内容 41 | $position = strpos($url, '?'); 42 | $url = $position === false ? $url : substr($url, 0, $position); 43 | 44 | // 使得可以这样访问 index.php/{controller}/{action} 45 | $position = strpos($url, 'index.php'); 46 | if ($position !== false) { 47 | $url = substr($url, $position + strlen('index.php')); 48 | } 49 | 50 | // 删除前后的“/” 51 | $url = trim($url, '/'); 52 | 53 | if ($url) { 54 | // 使用“/”分割字符串,并保存在数组中 55 | $urlArray = explode('/', $url); 56 | // 删除空的数组元素 57 | $urlArray = array_filter($urlArray); 58 | 59 | // 获取控制器名 60 | $controllerName = ucfirst($urlArray[0]); 61 | 62 | // 获取动作名 63 | array_shift($urlArray); 64 | $actionName = $urlArray ? $urlArray[0] : $actionName; 65 | 66 | // 获取URL参数 67 | array_shift($urlArray); 68 | $param = $urlArray ? $urlArray : array(); 69 | } 70 | 71 | // 判断控制器和操作是否存在 72 | $controller = 'app\\controllers\\'. $controllerName . 'Controller'; 73 | if (!class_exists($controller)) { 74 | exit($controller . '控制器不存在'); 75 | } 76 | if (!method_exists($controller, $actionName)) { 77 | exit($actionName . '方法不存在'); 78 | } 79 | 80 | // 如果控制器和操作名存在,则实例化控制器,因为控制器对象里面 81 | // 还会用到控制器名和操作名,所以实例化的时候把他们俩的名称也 82 | // 传进去。结合Controller基类一起看 83 | $dispatch = new $controller($controllerName, $actionName); 84 | 85 | // $dispatch保存控制器实例化后的对象,我们就可以调用它的方法, 86 | // 也可以像方法中传入参数,以下等同于:$dispatch->$actionName($param) 87 | call_user_func_array(array($dispatch, $actionName), $param); 88 | } 89 | 90 | // 检测开发环境 91 | public function setReporting() 92 | { 93 | if (APP_DEBUG === true) { 94 | error_reporting(E_ALL); 95 | ini_set('display_errors','On'); 96 | } else { 97 | error_reporting(E_ALL); 98 | ini_set('display_errors','Off'); 99 | ini_set('log_errors', 'On'); 100 | } 101 | } 102 | 103 | // 删除敏感字符 104 | public function stripSlashesDeep($value) 105 | { 106 | $value = is_array($value) ? array_map(array($this, 'stripSlashesDeep'), $value) : stripslashes($value); 107 | return $value; 108 | } 109 | 110 | // 检测敏感字符并删除 111 | public function removeMagicQuotes() 112 | { 113 | if (get_magic_quotes_gpc()) { 114 | $_GET = isset($_GET) ? $this->stripSlashesDeep($_GET ) : ''; 115 | $_POST = isset($_POST) ? $this->stripSlashesDeep($_POST ) : ''; 116 | $_COOKIE = isset($_COOKIE) ? $this->stripSlashesDeep($_COOKIE) : ''; 117 | $_SESSION = isset($_SESSION) ? $this->stripSlashesDeep($_SESSION) : ''; 118 | } 119 | } 120 | 121 | // 检测自定义全局变量并移除。因为 register_globals 已经弃用,如果 122 | // 已经弃用的 register_globals 指令被设置为 on,那么局部变量也将 123 | // 在脚本的全局作用域中可用。 例如, $_POST['foo'] 也将以 $foo 的 124 | // 形式存在,这样写是不好的实现,会影响代码中的其他变量。 相关信息, 125 | // 参考: http://php.net/manual/zh/faq.using.php#faq.register-globals 126 | public function unregisterGlobals() 127 | { 128 | if (ini_get('register_globals')) { 129 | $array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES'); 130 | foreach ($array as $value) { 131 | foreach ($GLOBALS[$value] as $key => $var) { 132 | if ($var === $GLOBALS[$key]) { 133 | unset($GLOBALS[$key]); 134 | } 135 | } 136 | } 137 | } 138 | } 139 | 140 | // 配置数据库信息 141 | public function setDbConfig() 142 | { 143 | if ($this->config['db']) { 144 | define('DB_HOST', $this->config['db']['host']); 145 | define('DB_NAME', $this->config['db']['dbname']); 146 | define('DB_USER', $this->config['db']['username']); 147 | define('DB_PASS', $this->config['db']['password']); 148 | } 149 | } 150 | 151 | // 自动加载类 152 | public function loadClass($className) 153 | { 154 | $classMap = $this->classMap(); 155 | 156 | if (isset($classMap[$className])) { 157 | // 包含内核文件 158 | $file = $classMap[$className]; 159 | } elseif (strpos($className, '\\') !== false) { 160 | // 包含应用(application目录)文件 161 | $file = APP_PATH . str_replace('\\', '/', $className) . '.php'; 162 | if (!is_file($file)) { 163 | return; 164 | } 165 | } else { 166 | return; 167 | } 168 | 169 | include $file; 170 | 171 | // 这里可以加入判断,如果名为$className的类、接口或者性状不存在,则在调试模式下抛出错误 172 | } 173 | 174 | // 内核文件命名空间映射关系 175 | protected function classMap() 176 | { 177 | return [ 178 | 'fastphp\base\Controller' => CORE_PATH . '/base/Controller.php', 179 | 'fastphp\base\Model' => CORE_PATH . '/base/Model.php', 180 | 'fastphp\base\View' => CORE_PATH . '/base/View.php', 181 | 'fastphp\db\Db' => CORE_PATH . '/db/Db.php', 182 | 'fastphp\db\Sql' => CORE_PATH . '/db/Sql.php', 183 | ]; 184 | } 185 | } -------------------------------------------------------------------------------- /fastphp/base/Controller.php: -------------------------------------------------------------------------------- 1 | _controller = $controller; 17 | $this->_action = $action; 18 | $this->_view = new View($controller, $action); 19 | } 20 | 21 | // 分配变量 22 | public function assign($name, $value) 23 | { 24 | $this->_view->assign($name, $value); 25 | } 26 | 27 | // 渲染视图 28 | public function render() 29 | { 30 | $this->_view->render(); 31 | } 32 | } -------------------------------------------------------------------------------- /fastphp/base/Model.php: -------------------------------------------------------------------------------- 1 | table) { 14 | 15 | // 获取模型类名称 16 | $this->model = get_class($this); 17 | 18 | // 删除类名最后的 Model 字符 19 | $this->model = substr($this->model, 0, -5); 20 | 21 | // 数据库表名与类名一致 22 | $this->table = strtolower($this->model); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /fastphp/base/View.php: -------------------------------------------------------------------------------- 1 | _controller = strtolower($controller); 16 | $this->_action = strtolower($action); 17 | } 18 | 19 | // 分配变量 20 | public function assign($name, $value) 21 | { 22 | $this->variables[$name] = $value; 23 | } 24 | 25 | // 渲染显示 26 | public function render() 27 | { 28 | extract($this->variables); 29 | $defaultHeader = APP_PATH . 'app/views/header.php'; 30 | $defaultFooter = APP_PATH . 'app/views/footer.php'; 31 | 32 | $controllerHeader = APP_PATH . 'app/views/' . $this->_controller . '/header.php'; 33 | $controllerFooter = APP_PATH . 'app/views/' . $this->_controller . '/footer.php'; 34 | $controllerLayout = APP_PATH . 'app/views/' . $this->_controller . '/' . $this->_action . '.php'; 35 | 36 | // 页头文件 37 | if (is_file($controllerHeader)) { 38 | include ($controllerHeader); 39 | } else { 40 | include ($defaultHeader); 41 | } 42 | 43 | //判断视图文件是否存在 44 | if (is_file($controllerLayout)) { 45 | include ($controllerLayout); 46 | } else { 47 | echo "

无法找到视图文件

"; 48 | } 49 | 50 | // 页脚文件 51 | if (is_file($controllerFooter)) { 52 | include ($controllerFooter); 53 | } else { 54 | include ($defaultFooter); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /fastphp/db/Db.php: -------------------------------------------------------------------------------- 1 | PDO::FETCH_ASSOC); 28 | 29 | return self::$pdo = new PDO($dsn, DB_USER, DB_PASS, $option); 30 | } catch (PDOException $e) { 31 | exit($e->getMessage()); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /fastphp/db/Sql.php: -------------------------------------------------------------------------------- 1 | where(['id = 1','and title="Web"', ...])->fetch(); 24 | * 为防止注入,建议通过$param方式传入参数: 25 | * $this->where(['id = :id'], [':id' => $id])->fetch(); 26 | * 27 | * @param array $where 条件 28 | * @return $this 当前对象 29 | */ 30 | public function where($where = array(), $param = array()) 31 | { 32 | if ($where) { 33 | $this->filter .= ' WHERE '; 34 | $this->filter .= implode(' ', $where); 35 | 36 | $this->param = $param; 37 | } 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * 拼装排序条件,使用方式: 44 | * 45 | * $this->order(['id DESC', 'title ASC', ...])->fetch(); 46 | * 47 | * @param array $order 排序条件 48 | * @return $this 49 | */ 50 | public function order($order = array()) 51 | { 52 | if($order) { 53 | $this->filter .= ' ORDER BY '; 54 | $this->filter .= implode(',', $order); 55 | } 56 | 57 | return $this; 58 | } 59 | 60 | // 查询所有 61 | public function fetchAll() 62 | { 63 | $sql = sprintf("select * from `%s` %s", $this->table, $this->filter); 64 | $sth = Db::pdo()->prepare($sql); 65 | $sth = $this->formatParam($sth, $this->param); 66 | $sth->execute(); 67 | 68 | return $sth->fetchAll(); 69 | } 70 | 71 | // 查询一条 72 | public function fetch() 73 | { 74 | $sql = sprintf("select * from `%s` %s", $this->table, $this->filter); 75 | $sth = Db::pdo()->prepare($sql); 76 | $sth = $this->formatParam($sth, $this->param); 77 | $sth->execute(); 78 | 79 | return $sth->fetch(); 80 | } 81 | 82 | // 根据条件 (id) 删除 83 | public function delete($id) 84 | { 85 | $sql = sprintf("delete from `%s` where `%s` = :%s", $this->table, $this->primary, $this->primary); 86 | $sth = Db::pdo()->prepare($sql); 87 | $sth = $this->formatParam($sth, [$this->primary => $id]); 88 | $sth->execute(); 89 | 90 | return $sth->rowCount(); 91 | } 92 | 93 | // 新增数据 94 | public function add($data) 95 | { 96 | $sql = sprintf("insert into `%s` %s", $this->table, $this->formatInsert($data)); 97 | $sth = Db::pdo()->prepare($sql); 98 | $sth = $this->formatParam($sth, $data); 99 | $sth = $this->formatParam($sth, $this->param); 100 | $sth->execute(); 101 | 102 | return $sth->rowCount(); 103 | } 104 | 105 | // 修改数据 106 | public function update($data) 107 | { 108 | $sql = sprintf("update `%s` set %s %s", $this->table, $this->formatUpdate($data), $this->filter); 109 | $sth = Db::pdo()->prepare($sql); 110 | $sth = $this->formatParam($sth, $data); 111 | $sth = $this->formatParam($sth, $this->param); 112 | $sth->execute(); 113 | 114 | return $sth->rowCount(); 115 | } 116 | 117 | /** 118 | * 占位符绑定具体的变量值 119 | * @param PDOStatement $sth 要绑定的PDOStatement对象 120 | * @param array $params 参数,有三种类型: 121 | * 1)如果SQL语句用问号?占位符,那么$params应该为 122 | * [$a, $b, $c] 123 | * 2)如果SQL语句用冒号:占位符,那么$params应该为 124 | * ['a' => $a, 'b' => $b, 'c' => $c] 125 | * 或者 126 | * [':a' => $a, ':b' => $b, ':c' => $c] 127 | * 128 | * @return PDOStatement 129 | */ 130 | public function formatParam(PDOStatement $sth, $params = array()) 131 | { 132 | foreach ($params as $param => &$value) { 133 | $param = is_int($param) ? $param + 1 : ':' . ltrim($param, ':'); 134 | $sth->bindParam($param, $value); 135 | } 136 | 137 | return $sth; 138 | } 139 | 140 | // 将数组转换成插入格式的sql语句 141 | private function formatInsert($data) 142 | { 143 | $fields = array(); 144 | $names = array(); 145 | foreach ($data as $key => $value) { 146 | $fields[] = sprintf("`%s`", $key); 147 | $names[] = sprintf(":%s", $key); 148 | } 149 | 150 | $field = implode(',', $fields); 151 | $name = implode(',', $names); 152 | 153 | return sprintf("(%s) values (%s)", $field, $name); 154 | } 155 | 156 | // 将数组转换成更新格式的sql语句 157 | private function formatUpdate($data) 158 | { 159 | $fields = array(); 160 | foreach ($data as $key => $value) { 161 | $fields[] = sprintf("`%s` = :%s", $key, $key); 162 | } 163 | 164 | return implode(',', $fields); 165 | } 166 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | run(); 16 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | ./tests/ 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/css/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 10px; 4 | font-size: 20px; 5 | } 6 | 7 | input { 8 | font-family:georgia,times; 9 | font-size:24px; 10 | line-height:1.2em; 11 | } 12 | 13 | a { 14 | color:blue; 15 | font-family:georgia,times; 16 | line-height:1.2em; 17 | text-decoration:none; 18 | } 19 | 20 | a:hover { 21 | text-decoration:underline; 22 | } 23 | 24 | h1 { 25 | color:#000000; 26 | font-size:41px; 27 | border-bottom:1px dotted #cccccc; 28 | } 29 | 30 | td {padding: 1px 30px 1px 0;} -------------------------------------------------------------------------------- /tests/autoload.php: -------------------------------------------------------------------------------- 1 |