自定义 Yii Module 路由
安装项目⌗
我这里选用的是 yii advanced 版本,如果你没有运行环境的话可以参考官方的文档,使用 Vagrant 安装运行环境。
因为我本地已经有了 PHP 运行环境,所以直接使用 Composer 创建项目:
composer create-project --prefer-dist yiisoft/yii2-app-advanced service
进入项目目录,初始化项目:
$ 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.
安装完成后目录结构如下:
$ 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:
$ 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:
'modules' => [
'auth' => ['class' => 'backend\modules\auth\Module'],
],
并修改 urlManager
属性如下:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'<modules>/<controller>' => '<modules>/<controller>/enter'
],
],
主要是 rules
部分,将所有的请求路由到对应 Module 的相应 Controller 中的 enter 方法,这么做的目的是可以对所有请求统一进行处理。
处理统一逻辑的控制器⌗
创建控制器⌗
创建 common\controllers\RestController.php
控制器,内容如下:
<?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 <[email protected]>
* @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 <[email protected]>
*/
public function post(array $params = []): array
{
return [];
}
/**
* Date: 2019/1/1
* @param array $params
* @return array
* @author George <[email protected]>
*/
public function put(array $params = []): array
{
return [];
}
/**
* Date: 2019/1/1
* @param array $params
* @return array
* @author George <[email protected]>
*/
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 <[email protected]>
*/
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
。
<?php
namespace backend\modules\auth\controllers;
use common\controllers\RestController;
/**
* User SingIn Controller logic
*
* Date: 2019/1/1
* @author George <[email protected]>
* @package backend\modules\auth\controllers
*/
class SigninController extends RestController
{
public function post(array $params = []): array
{
return $params;
}
}
到这里基本上就完成了,此时请求 POST /auth/signin
,将会自动路由到 SigninController
的 post
方法。
I hope this is helpful, Happy hacking…