## 创建core/RouteCollection.php
````
<?php
namespace core;
use core\request\RequestInterface;
Class RouteCollection
{
protected $routes = []; // 所有路由存放
protected $route_index = 0; // 当前访问的路由
public function getRoutes() // 获取所有路由
{
return $this->routes;
}
public $currGroup = []; // 当前组
public function group($attributes = [],\Closure $callback)
{
$this->currGroup[] = $attributes;
call_user_func($callback,$this);
// $callback($this); 跟这个一样的效果
// group的实现主要的这个$this 这个$this将当前状态传递到了闭包
array_pop($this->currGroup);
}
// 增加/ 如: GETUSER 改成 GET/USER
protected function addSlash(& $uri)
{
return $uri[0] == '/' ? : $uri = '/'.$uri;
}
// 增加路由
public function addRoute($method,$uri,$uses)
{
$prefix = ''; // 前缀
$middleware = []; // 中间件
$namespace = ''; // 命名空间
$this->addSlash($uri);
foreach ($this->currGroup as $group){
$prefix .= $group['prefix'] ?? false;
if( $prefix) // 如果有前缀
$this->addSlash($prefix);
$middleware = $group['middleware'] ?? []; // 合并组中间件
$namespace .= $group['namespace'] ?? ''; // 拼接组的命名空间
}
$method = strtoupper($method); // 请求方式 转大写
$uri = $prefix .$uri;
$this->route_index = $method . $uri; // 路由索引
$this->routes[$this->route_index] = [ // 路由存储结构 用 GET/USER 这种方式做索引 一次性就找到了
'method' => $method, // 请求类型
'uri' => $uri, // 请求url
'action' => [
'uses' => $uses,
'middleware' => $middleware,
'namespace' => $namespace
]
];
}
public function get($uri,$uses)
{
$this->addRoute('get',$uri,$uses);
return $this;
}
public function post($uri,$uses)
{
$this->addRoute('post',$uri,$uses);
return $this;
}
public function put($uri,$uess){} // 略写 ...
public function delete($uri,$uses){}
public function middleware($class)
{
$this->routes[$this->route_index]['action']['middleware'][] = $class;
return $this;
}
// 获取当前访问的路由
public function getCurrRoute()
{
$routes = $this->getRoutes();
$route_index = $this->route_index;
if( isset( $routes[ $route_index]))
return $routes[ $route_index];
$route_index .= '/';
if( isset( $routes[ $route_index]))
return $routes[ $route_index];
return false;
}
// 更具request执行路由
public function dispatch(RequestInterface $request)
{
$method = $request->getMethod();
$uri = $request->getUri();
$this->route_index = $method . $uri;
$route = $this->getCurrRoute();
if(! $route) // 找不到路由
return 404;
$routerDispatch = $route['action']['uses'];
return $routerDispatch();
}
}
````
## 绑定路由
编辑 `app.php`
![](https://img.kancloud.cn/1f/36/1f362c470402b9dbb537798e5d5dfc25_528x202.png)
## 加载路由文件
编辑 `app.php` 的 `boot`方法
```
App::getContainer()->get('router')->group([
'namespace' => 'App\\controller'
], function ($router){
require_once FRAME_BASE_PATH . '/routes/web.php'; // 因为是require 所以web.php有$router这个变量
});
App::getContainer()->get('router')->group([
'namespace' => 'App\\controller',
'prefix' => 'api'
], function ($router){
require_once FRAME_BASE_PATH . '/routes/api.php';
});
```
![](https://img.kancloud.cn/8f/9f/8f9f6e2eb5d0c538bac1f22b4f94145f_947x394.png)
## 创建routes/web.php和routes/api.php
编辑 `routes/web.php`:
![](https://img.kancloud.cn/33/6f/336fdbbbad85d567797139589be80064_643x308.png)
## 编辑index.php
![](https://img.kancloud.cn/21/39/213999e21a389b4a7fc0708d74ad3cae_748x620.png)
```
App::getContainer()->get('response')->setContent(
App::getContainer()->get('router')->dispatch(
App::getContainer()->get(\core\request\RequestInterface::class)
)
)->send();
```
## 运行
![](https://img.kancloud.cn/bf/9f/bf9ffbb7abed96f7a82aa8c2df2ac2b1_519x283.png)
- 前言
- 基础篇
- 1. 第一步 创建框架目录结构
- 2. 引入composer自动加载
- 3. php自动加载 (解释篇)
- 4. 创建容器 注册树模式
- 5. 关于psr规范解释
- 6. 关于"容器" "契约" "依赖注入" (解释篇)
- 7. 添加函数文件helpers.php
- 8. 初始化请求(Request)
- 9. 响应 (Response)
- 10. 路由一 (路由组实现)
- 11. 路由二 (加入中间件)
- 12. 配置信息 (类似laravel)
- 13. 数据库连接 (多例模式)
- 14. 查询构造器 (query builder)
- MVC实现
- M 模型实现 (数据映射 + 原型 模式)
- C 控制器实现 + 控制器中间件
- V 视图实现 (Laravel Blade 引擎)
- V 视图切换成 ThinkPhp 模板 引擎)
- 其他轮子
- 日志
- 自定义异常 (异常托管)
- 单元测试 (phpunit)
- 替换成swoole的http服务器
- 协程上下文解决request问题
- qps测试
- 发布到packagist.org