Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修复utils bug,更新文档,路由添加options方式注册 #43

Merged
merged 15 commits into from
Aug 21, 2022
124 changes: 90 additions & 34 deletions docs/zh-cn/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,61 +92,117 @@ $conatiner->call(callable $callable, array $arguments = []);

## max/routing

一款简单的可以独立使用的路由
### 初始化

### 安装

```shell
composer require max/routing
```php
$router = new Router(array $options = [], ?Max\Routing\RouteCollector $routeCollector);
```

如果传递给Router类的路由收集器是null,则内部会自动实例化

### 使用

```php
#### 支持GET, POST, PUT, PATCH, DELETE等方法,例如:

$router = new Router();
```
$router->get('/', function() {
// Do something.
});
```

如果需要一个路由注册自定义请求方法,例如:

```
$router->request('/', function() {
// Do something.
}, ['GET’, 'OPTION']);
```

$router->get('index/{name}', function($name) {
return $name;
如果需要一个路由支持所有请求方法,例如:

```
$router->any('/', function() {
// Do something.
});
```

// 路由分组示例
$router->prefix('api')
->middleware('class_name')
->pattterns(['id' => '\d+'])
->group(function(Router $router) {
$router->get('/user/{id}', function($id = 0) {
var_dump('user');
})->middlewares('auth');
$router->middleware('user')->group(function() {
// 使用引入文件的方式
require_once './route.php';
});
});

#### 如果需要注册一个Restful路由,例如:

```
$router->rest('/book', 'BookController');
```

Restful规则会注册多条路由,上面的规则注册的路由如下:

| Methods | Uri | Action |
| --- | --- | --- |
| GET/HEAD | /book | BookController@index |
| GET/HEAD | /book/{id} | BookController@show |
| POST | /book | BookController@store |
| PUT/PATCH | /book/{id} | BookController@update |
| DELETE | /book/{id} | BookController@delete |

值得注意的是rest方法返回的是一个RestRouter对象,通过该对象,你可以获取到某一个action对应的路由规则,并且注册其他参数,例如:

```php
$rest = $router->rest('/book', 'BookController');
$rest->getShowRoute()->middleware('JWTAuthentication');
```

#### 路由支持参数,例如:

```php
// 带参数类型限制, 其中id只有为数字的时候会匹配到
$router->get('/book/{id:\d+}', 'BookController@show');
// 带后缀的路由,注意这里的符号.会被解析成正则元字符的一部分,因此有必要添加反斜线转义
$router->get('/p/{id}\.html', 'CateController@show');
```


#### 路由支持分组并且支持分组嵌套,例如:

```php
$router->prefix('api')->group(function(\Max\Routing\Router $router) {
$router->middleware('Authentication')->group(function(\Max\Routing\Router $router) {
$router->get('/', function(\Max\Routing\Router $router) {
// Do something.
});

$router->where('id', '\d+')->get('/user/{id}', 'UserController@show');
});
```

上面的规则定义两条路由规则,第一条请求方式为GET,path为`/api`的路由规则,且中间件包含`Authentication`,第二条相相对于第一条还加了参数类型限制,此时id参数只能是数字

> 分组路由前置方法支持`prefix`, `namespace`, `middleware`, `where` 等

对于分组路由,你还可以在闭包中通过引入文件的方式来注册,例如:

```php
$router->group(function(\Max\Routing\Router $router) {
// 使用引入文件的方式
require_once './route.php';
});
```

// 解析路由,返回匹配到的Route对象
$route = $router->getRouteCollector()->resolve('GET', '/');
// 或者直接解析ServerRequestInterface对象
$route = $router->getRouteCollector()->resolveRequest($request);
在文件中的路由均使用$router来注册

var_dump($route);
#### 解析路由

解析路由使用路由收集器来完成,如果你没有使用外部,则可以使用Router对象提供的方法获取

```php
$routeCollector = $router->getRouteCollector();
```

此外还有一系列方法,例如
解析方法有两个

```php
$router->namespace('App\Http\Controllers')->get('/', 'Index@index');
$route = $routeCollector->resolve('GET', '/'); // 传递请求方式和path
$route = $routeCollector->resolveRequest($request); // 传递一个Psr\Http\Message\ServerRequestInterface对象进行解析
```

- prefix
- middleware
- namespace
- patterns
解析完成后会返回一个匹配到的路由的克隆对象,该对象中保存的对应变量,如果没有匹配到,则会抛出相应异常

## max/event

Expand Down
22 changes: 3 additions & 19 deletions docs/zh-cn/framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,29 +64,13 @@ class User

## 路由定义

> 在`app/Http/Kernel.php`的`map`方法中注册路由,例如

```php
protected function map(Router $router) {
$router->group(function(Router $router) {
$router->get('/', function(ServerRequestInterface $request) {
return $request->all();
});
$router->group(function() {
// 引入文件的方式
include_once 'routes.php';
});
});
}
```

> 也可以使用注解方式
在`app/Http/Kernel.php`的`map`方法中注册路由,注册方式请参考max/routing组件文档,或者使用注解方式

```php
#[Controller(prefix: 'index', middleware: [BasicAuthentication::class])]
class Index
{
#[GetMapping(path: '/user/{id}.html', domain: '*.1kmb.com')]
#[GetMapping(path: '/user/{id}\.html')]
public function index(\Psr\Http\Message\ServerRequestInterface $request, $id)
{
return new \Max\Http\Message\Response(200, [], 'Hello, world!');
Expand All @@ -112,7 +96,7 @@ class IntexController {

#[GetMapping(path: '/{id}')]
public functin index(ServerRequestInterface $request, $id) {
return ['test'];
// Do something.
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions src/aop/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"require": {
"php": "^8.0",
"ext-pcntl": "*",
"max/utils": "^1.0",
"max/di": "^1.0",
"max/utils": "dev-master",
"max/di": "dev-master",
"nikic/php-parser": "^4.13",
"symfony/finder": "*"
}
Expand Down
4 changes: 2 additions & 2 deletions src/cache/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
},
"require": {
"php": "^8.0",
"max/utils": "^1.0",
"max/utils": "dev-master",
"psr/simple-cache": "^1.0",
"max/redis": "^1.0"
"max/redis": "dev-master"
},
"extra": {
"max": {
Expand Down
2 changes: 1 addition & 1 deletion src/config/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"require": {
"php": "^8.0",
"max/utils": "^1.0"
"max/utils": "dev-master"
},
"extra": {
"max": {
Expand Down
2 changes: 1 addition & 1 deletion src/config/src/Contract/ConfigInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@

interface ConfigInterface
{
public function get(string $key, $default = null);
public function get(string $key, mixed $default = null);
}
8 changes: 3 additions & 5 deletions src/config/src/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,16 @@ class Repository implements ConfigInterface

/**
* 获取[支持点语法].
* @param null|mixed $default
*/
public function get(string $key, $default = null): mixed
public function get(string $key, mixed $default = null): mixed
{
return Arr::get($this->items, $key, $default);
}

/**
* 设置[支持点语法].
* @param mixed $value
* 设置[支持点语法]. Swoole/WorkerMan等环境下不可使用.
*/
public function set(string $key, $value): void
public function set(string $key, mixed $value): void
{
Arr::set($this->items, $key, $value);
}
Expand Down
6 changes: 3 additions & 3 deletions src/database/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
"php": "^8.0",
"ext-pdo": "*",
"ext-json": "*",
"max/utils": "^1.0",
"max/config": "^1.0",
"max/context": "^1.0"
"max/utils": "dev-master",
"max/config": "dev-master",
"max/context": "dev-master"
},
"extra": {
"max": {
Expand Down
35 changes: 19 additions & 16 deletions src/framework/src/Console/Command/RouteListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Closure;
use Max\Di\Exception\NotFoundException;
use Max\Routing\Route;
use Max\Routing\RouteCollector;
use Max\Utils\Collection;
use Psr\Container\ContainerExceptionInterface;
use ReflectionException;
Expand All @@ -37,17 +36,10 @@ public function execute(InputInterface $input, OutputInterface $output)
$table = new Table(new ConsoleOutput());
$table->setHeaders(['Methods', 'URI', 'Action', 'Middlewares']);
foreach ($this->getRoutes() as $route) {
/** @var Route $route */
$action = $route->getAction();
if (is_array($action)) {
$action = implode('::', $action);
} elseif ($action instanceof Closure) {
$action = 'Closure';
}
$table->addRow([
implode('|', $route->getMethods()),
$route->getPath(),
$action,
$this->formatRouteAction($route),
implode(PHP_EOL, $route->getMiddlewares()),
]);
}
Expand All @@ -68,19 +60,30 @@ protected function configure()
*/
protected function getRoutes(): Collection
{
make(Kernel::class);
$routeCollector = make(RouteCollector::class);
$kernel = make(Kernel::class);
$routes = [];
foreach ($routeCollector->all() as $registeredRoute) {
foreach ($kernel->getAllRoutes() as $registeredRoute) {
foreach ($registeredRoute as $route) {
if (! in_array($route, $routes)) {
$routes[] = $route;
}
}
}
return Collection::make($routes)->unique()->sortBy(function ($item) {
/* @var Route $item */
return $item->getPath();
});
return Collection::make($routes)->unique();
}

/**
* 格式化action为string.
*/
protected function formatRouteAction(Route $route): string
{
$action = $route->getAction();
if ($action instanceof Closure) {
return 'Closure';
}
if (is_array($action)) {
return implode('@', $action);
}
return $action;
}
}
2 changes: 1 addition & 1 deletion src/http-message/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"require": {
"php": "^8.0",
"psr/http-message": "^1.0",
"max/utils": "^1.0"
"max/utils": "dev-master"
}
}
32 changes: 19 additions & 13 deletions src/http-message/src/Contract/HeaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,37 @@

interface HeaderInterface
{
public const HEADER_CONTENT_TYPE = 'Content-Type';
public const HEADER_CONTENT_TYPE = 'Content-Type';

public const HEADER_SET_COOKIE = 'Set-Cookie';
public const HEADER_SET_COOKIE = 'Set-Cookie';

public const HEADER_PRAGMA = 'Pragma';
public const HEADER_PRAGMA = 'Pragma';

public const HEADER_ACCEPT = 'Accept';
public const HEADER_ACCEPT = 'Accept';

public const HEADER_EXPIRES = 'Expires';
public const HEADER_EXPIRES = 'Expires';

public const HEADER_CACHE_CONTROL = 'Cache-Control';
public const HEADER_CACHE_CONTROL = 'Cache-Control';

public const HEADER_CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding';
public const HEADER_X_FORWARDED_FOR = 'X-Forwarded-For';

public const HEADER_CONTENT_DISPOSITION = 'Content-Disposition';
public const HEADER_CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding';

public const HEADER_ORIGIN = 'Origin';
public const HEADER_CONTENT_DISPOSITION = 'Content-Disposition';

public const HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin';
public const HEADER_AUTHORIZATION = 'Authorization';

public const HEADER_ACCESS_CONTROL_MAX_AGE = 'Access-Control-Max-Age';
public const HEADER_X_REQUESTED_WITH = 'X-Requested-With';

public const HEADER_ORIGIN = 'Origin';

public const HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin';

public const HEADER_ACCESS_CONTROL_MAX_AGE = 'Access-Control-Max-Age';

public const HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials';

public const HEADER_ACCESS_CONTROL_ALLOW_METHODS = 'Access-Control-Allow-Methods';
public const HEADER_ACCESS_CONTROL_ALLOW_METHODS = 'Access-Control-Allow-Methods';

public const HEADER_ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers';
public const HEADER_ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers';
}
Loading