自定义 Yii Module 路由

自定义 Yii Module 路由

现在大多数公司在用框架的时候,都会对框架原有的特性或规则进行一定程度的定制,使其更符合公司的实际开发场景。

安装项目

我这里选用的是 yii advanced 版本,如果你没有运行环境的话可以参考官方的文档,使用 Vagrant 安装运行环境。

因为我本地已经有了 PHP 运行环境,所以直接使用 Composer 创建项目:

1
composer create-project --prefer-dist yiisoft/yii2-app-advanced service

进入项目目录,初始化项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ cd service
$ php init
Yii Application Initialization Tool v1.0

Which environment do you want the application to be initialized in?

[0] Development
[1] Production

Your choice [0-1, or "q" to quit] 0

Initialize the application under 'Development' environment? [yes|no] yes

Start initialization ...

generate frontend/config/test-local.php
generate frontend/config/params-local.php
generate frontend/config/main-local.php
generate frontend/config/codeception-local.php
generate frontend/web/index.php
generate frontend/web/robots.txt
generate frontend/web/index-test.php
generate yii
generate backend/config/test-local.php
generate backend/config/params-local.php
generate backend/config/main-local.php
generate backend/config/codeception-local.php
generate backend/web/index.php
generate backend/web/robots.txt
generate backend/web/index-test.php
generate common/config/test-local.php
generate common/config/params-local.php
generate common/config/main-local.php
generate common/config/codeception-local.php
generate yii_test.bat
generate yii_test
generate console/config/test-local.php
generate console/config/params-local.php
generate console/config/main-local.php
generate cookie validation key in backend/config/main-local.php
generate cookie validation key in common/config/codeception-local.php
generate cookie validation key in frontend/config/main-local.php
chmod 0777 backend/runtime
chmod 0777 backend/web/assets
chmod 0777 console/runtime
chmod 0777 frontend/runtime
chmod 0777 frontend/web/assets
chmod 0755 yii
chmod 0755 yii_test

... initialization completed.

安装完成后目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ tree -L 1
.
├── LICENSE.md
├── README.md
├── Vagrantfile
├── backend
├── codeception.yml
├── common
├── composer.json
├── composer.lock
├── console
├── docker-compose.yml
├── environments
├── frontend
├── init
├── init.bat
├── requirements.php
├── vagrant
├── vendor
├── yii
├── yii.bat
├── yii_test
└── yii_test.bat

7 directories, 14 files

接下来我们将对 backend app 下的路由功能进行改造。

Module

生成

使用 gii 来为项目生成 Module,可以看到下面我生成了一个 auth 的 Module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ php yii gii/module --moduleClass='backend\modules\auth\Module' --moduleID=auth
Running 'Module Generator'...

The following files will be generated:
[new] /Users/George/Develop/PHP/service/backend/modules/auth/Module.php
[new] /Users/George/Develop/PHP/service/backend/modules/auth/controllers/DefaultController.php
[new] /Users/George/Develop/PHP/service/backend/modules/auth/views/default/index.php

Ready to generate the selected files? (yes|no) [yes]:yes

Files were generated successfully!
Generating code using template "/Users/George/Develop/PHP/service/vendor/yiisoft/yii2-gii/src/generators/module/default"...
generated /Users/George/Develop/PHP/service/backend/modules/auth/Module.php
generated /Users/George/Develop/PHP/service/backend/modules/auth/controllers/DefaultController.php
generated /Users/George/Develop/PHP/service/backend/modules/auth/views/default/index.php
done!

注册

编辑 backend\config\main.php 文件,在 modules 中添加 auth Module:

1
2
3
'modules' => [
'auth' => ['class' => 'backend\modules\auth\Module'],
],

并修改 urlManager 属性如下:

1
2
3
4
5
6
7
8
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'<modules>/<controller>' => '<modules>/<controller>/enter'
],
],

主要是 rules 部分,将所有的请求路由到对应 Module 的相应 Controller 中的 enter 方法,这么做的目的是可以对所有请求统一进行处理。

处理统一逻辑的控制器

创建控制器

创建 common\controllers\RestController.php 控制器,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?php

namespace common\controllers;

use Yii;
use yii\base\Action;
use ReflectionException;
use yii\rest\Controller;
use yii\base\InlineAction;
use yii\base\InvalidRouteException;
use yii\base\InvalidConfigException;

/**
* Date: 2019/1/1
* @author George
* @package common\controllers
*/
class BaseController extends Controller
{
/**
* 统一处理请求
*
* Date: 2019/1/1
* @return mixed
* @throws InvalidRouteException
* @author George
*/
public function main()
{
$request = Yii::$app->request;
$method = strtolower($request->getMethod());
$params = array_merge($request->get(), $request->post());
// 你需要统一处理的业务逻辑
$result = $this->runAction($method, ['params' => $params]);
return $result;
}

/**
* Date: 2019/1/1
* @param array $params
* @return array
* @author George
*/
public function post(array $params = []): array
{
return [];
}

/**
* Date: 2019/1/1
* @param array $params
* @return array
* @author George
*/
public function put(array $params = []): array
{
return [];
}

/**
* Date: 2019/1/1
* @param array $params
* @return array
* @author George
*/
public function get(array $params = []): array
{
return [];
}

/**
* 使用 index 方法名替代 actionIndex 这种方式
*
* Date: 2019/1/1
* @param string $id
* @return object|Action|InlineAction|null
* @throws ReflectionException
* @throws InvalidConfigException
* @author George
*/
public function createAction($id)
{
if ($id === '') {
$id = $this->defaultAction;
}

$actionMap = $this->actions();
if (isset($actionMap[$id])) {
return Yii::createObject($actionMap[$id], [$id, $this]);
}

if (preg_match('/^(?:[a-z0-9_]+-)*[a-z0-9_]+$/', $id)) {
$methodName = $id;
if (method_exists($this, $methodName)) {
$method = new \ReflectionMethod($this, $methodName);
if ($method->isPublic() && $method->getName() === $methodName) {
return new InlineAction($id, $this, $methodName);
}
}
}

return null;
}
}

继承控制器

让项目中的 Module Controller 都继承自上面创建的 common\controllers\RestController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace backend\modules\auth\controllers;

use common\controllers\RestController;

/**
* User SingIn Controller logic
*
* Date: 2019/1/1
* @author George
* @package backend\modules\auth\controllers
*/
class SigninController extends RestController
{
public function post(array $params = []): array
{
return $params;
}
}

到这里基本上就完成了,此时请求 POST /auth/signin,将会自动路由到 backend\modules\auth\controllers\SigninControllerpost 方法。

评论