基于 yiisoft/yii2-app-advanced,在 GitHub 上新建仓库 yii2-app-advanced,新建接口应用(实现 RESTful 风格的 Web Service 服务的 API),实现模型分层:数据层、逻辑层,明确公共目录、应用、模块的继承、引用关系 (二)
1、定义与规范:
定义:
(1)数据层:models 用于定义数据相关的自动验证和自动完成和数据存取接口;
(2)逻辑层:logics 用于定义数据相关的业务逻辑;
规范:
(1)/common/models 目录中的模型类文件仅允许Gii工具所生成,为公共的模型数据层;
(2)/common/logics 目录中的模型类文件为业务逻辑相关,继承至 /common/models 数据层,为公共的模型逻辑层;
(3)/common 目录中需要引用模型类文件,仅引用 /common/logics 中的模型类文件,例:
1 | public $modelClass = 'common\logics\User' ; |
(4)/api/models、/backend/models、/frontend/models 目录中的模型类文件为业务逻辑相关(仅与各应用相关),继承至 /common/logics 公共逻辑层;
(5)接口、前端、后端应用目录中需要引用模型类文件,仅引用各自目录下的对应模型类文件,例:
1 | use api\models\User; |
(6)/api/modules/v1/models 目录中的模型类文件为业务逻辑相关(仅与模块相关),继承至 /api/models 应用逻辑层;
(7)模块目录中需要引用模型类文件,仅引用各自模块下的对应模型类文件,例:
1 | public $modelClass = 'api\modules\v1\models\User' ; |
2、在common目录中新建logics目录,用于MySQL模型的逻辑层所在目录,如图1
3、复制 \common\models\LoginForm.php、\common\models\User.php 至 \common\logics,如图2
4、在common/models目录中的MySQL模型文件仅为Gii工具所生成,删除 \common\models\LoginForm.php,如图3
5、配置路由,使用美观的 URL ,编辑 \frontend\config\main.php
1 2 3 4 5 6 | 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ ], ], |
6、国际化的支持,新建目录 \common\messages\en-US\model、\common\messages\zh-CN\model,分别用于模型的数据层的美国英语、中文简体;新建 \common\messages\{language}\app.php、\common\messages\{language}\error.php、\common\messages\{language}\success.php,分别用于应用全局消息、应用错误消息、应用成功消息,如图4
app.php
1 2 3 | <?php return [ ]; |
error.php
1 2 3 4 | <?php return [ 20000 => 'error' , ]; |
success.php
1 2 3 4 | <?php return [ 10000 => 'success' , ]; |
7、配置应用程序语言,源语言为美国英语,目标语言为简体中文,当源语言和目标语言相同时,是否强制进行消息翻译,默认为假,设置为真,编辑 \common\config\main.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 'sourceLanguage' => 'en-US' , 'language' => 'zh-CN' , 'components' => [ 'i18n' => [ 'translations' => [ '*' => [ 'class' => 'yii\i18n\PhpMessageSource' , 'forceTranslation' => true, 'basePath' => '@common/messages' , 'fileMap' => [ 'app' => 'app.php' , 'error' => 'error.php' , 'success' => 'success.php' , ], ], ], ], 'cache' => [ 'class' => 'yii\caching\FileCache' , ], ], |
8、打开网址:http://www.github-shuijingwan-yii2-app-advanced.localhost/gii/model ,选项,命名空间为common\models,此时需支持国际化,覆盖\common\models\User.php,如图5
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 | <?php namespace common\models; use Yii; /** * This is the model class for table "{{%user}}". * * @property int $id * @property string $username * @property string $auth_key * @property string $password_hash * @property string $password_reset_token * @property string $email * @property int $status * @property int $created_at * @property int $updated_at */ class User extends \yii\db\ActiveRecord { /** * @inheritdoc */ public static function tableName() { return '{{%user}}' ; } /** * @inheritdoc */ public function rules() { return [ [[ 'username' , 'auth_key' , 'password_hash' , 'email' , 'created_at' , 'updated_at' ], 'required' ], [[ 'status' , 'created_at' , 'updated_at' ], 'integer' ], [[ 'username' , 'password_hash' , 'password_reset_token' , 'email' ], 'string' , 'max' => 255], [[ 'auth_key' ], 'string' , 'max' => 32], [[ 'username' ], 'unique' ], [[ 'email' ], 'unique' ], [[ 'password_reset_token' ], 'unique' ], ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => Yii::t( 'model/user' , 'ID' ), 'username' => Yii::t( 'model/user' , 'Username' ), 'auth_key' => Yii::t( 'model/user' , 'Auth Key' ), 'password_hash' => Yii::t( 'model/user' , 'Password Hash' ), 'password_reset_token' => Yii::t( 'model/user' , 'Password Reset Token' ), 'email' => Yii::t( 'model/user' , 'Email' ), 'status' => Yii::t( 'model/user' , 'Status' ), 'created_at' => Yii::t( 'model/user' , 'Created At' ), 'updated_at' => Yii::t( 'model/user' , 'Updated At' ), ]; } } |
9、在common/logics目录中的MySQL模型文件为业务逻辑相关,继承至 \common\models 数据层,打开网址:http://www.github-shuijingwan-yii2-app-advanced.localhost/gii/model ,选项,如图6
10、基于 diff ,编辑 \common\logics\User.php,如图7
11、在common/logics目录中的MySQL模型文件为业务逻辑相关,继承至 \common\models\User 数据层
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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | <?php namespace common\logics; use Yii; use yii\base\NotSupportedException; use yii\behaviors\TimestampBehavior; use yii\web\IdentityInterface; /** * This is the model class for table "{{%user}}". * * @property int $id * @property string $username * @property string $auth_key * @property string $password_hash * @property string $password_reset_token * @property string $email * @property int $status * @property int $created_at * @property int $updated_at * @property string $password write-only password */ class User extends \common\models\User implements IdentityInterface { const STATUS_DELETED = 0; const STATUS_ACTIVE = 10; /** * @inheritdoc */ public function behaviors() { return [ TimestampBehavior::className(), ]; } /** * @inheritdoc */ public function rules() { return [ [[ 'username' , 'auth_key' , 'password_hash' , 'email' ], 'required' ], [[ 'status' , 'created_at' , 'updated_at' ], 'integer' ], [[ 'username' , 'password_hash' , 'password_reset_token' , 'email' ], 'string' , 'max' => 255], [[ 'auth_key' ], 'string' , 'max' => 32], [[ 'username' ], 'unique' ], [[ 'email' ], 'unique' ], [[ 'password_reset_token' ], 'unique' ], [ 'status' , 'default' , 'value' => self::STATUS_ACTIVE], [ 'status' , 'in' , 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], ]; } /** * @inheritdoc */ public static function findIdentity( $id ) { return static ::findOne([ 'id' => $id , 'status' => self::STATUS_ACTIVE]); } /** * @inheritdoc */ public static function findIdentityByAccessToken( $token , $type = null) { throw new NotSupportedException( '"findIdentityByAccessToken" is not implemented.' ); } /** * Finds user by username * * @param string $username * @return static|null */ public static function findByUsername( $username ) { return static ::findOne([ 'username' => $username , 'status' => self::STATUS_ACTIVE]); } /** * Finds user by password reset token * * @param string $token password reset token * @return static|null */ public static function findByPasswordResetToken( $token ) { if (! static ::isPasswordResetTokenValid( $token )) { return null; } return static ::findOne([ 'password_reset_token' => $token , 'status' => self::STATUS_ACTIVE, ]); } /** * Finds out if password reset token is valid * * @param string $token password reset token * @return bool */ public static function isPasswordResetTokenValid( $token ) { if ( empty ( $token )) { return false; } $timestamp = (int) substr ( $token , strrpos ( $token , '_' ) + 1); $expire = Yii:: $app ->params[ 'user.passwordResetTokenExpire' ]; return $timestamp + $expire >= time(); } /** * @inheritdoc */ public function getId() { return $this ->getPrimaryKey(); } /** * @inheritdoc */ public function getAuthKey() { return $this ->auth_key; } /** * @inheritdoc */ public function validateAuthKey( $authKey ) { return $this ->getAuthKey() === $authKey ; } /** * Validates password * * @param string $password password to validate * @return bool if password provided is valid for current user */ public function validatePassword( $password ) { return Yii:: $app ->security->validatePassword( $password , $this ->password_hash); } /** * Generates password hash from password and sets it to the model * * @param string $password */ public function setPassword( $password ) { $this ->password_hash = Yii:: $app ->security->generatePasswordHash( $password ); } /** * Generates "remember me" authentication key */ public function generateAuthKey() { $this ->auth_key = Yii:: $app ->security->generateRandomString(); } /** * Generates new password reset token */ public function generatePasswordResetToken() { $this ->password_reset_token = Yii:: $app ->security->generateRandomString() . '_' . time(); } /** * Removes password reset token */ public function removePasswordResetToken() { $this ->password_reset_token = null; } } |
12、新建 \common\messages\en-US\model\user.php,支持目标语言为英语美国时的消息翻译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 10:34 */ return [ 'ID' => 'ID' , 'Username' => 'Username' , 'Auth Key' => 'Auth Key' , 'Password Hash' => 'Password Hash' , 'Password Reset Token' => 'Password Reset Token' , 'Email' => 'Email' , 'Status' => 'Status' , 'Created At' => 'Created At' , 'Updated At' => 'Updated At' , ]; |
13、新建 \common\messages\zh-CN\model\user.php,支持目标语言为简体中文时的消息翻译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 10:39 */ return [ 'ID' => 'ID' , 'Username' => '用户名' , 'Auth Key' => '认证密钥' , 'Password Hash' => '密码哈希' , 'Password Reset Token' => '密码重置令牌' , 'Email' => '邮箱' , 'Status' => '状态' , 'Created At' => '创建时间' , 'Updated At' => '更新时间' , ]; |
14、新建 \api\models\User.php,在api/models目录中的MySQL模型文件为业务逻辑相关(仅与api相关),继承至 \common\logics\User 逻辑层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 10:44 */ namespace api\models; class User extends \common\logics\User { } |
15、复制\api\models\User.php 至 \frontend\models\User.php、\backend\models\User.php,调整为各自的命名空间
\frontend\models\User.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 10:44 */ namespace frontend\models; class User extends \common\logics\User { } |
\backend\models\User.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 10:44 */ namespace backend\models; class User extends \common\logics\User { } |
16、在 api 应用中搜索 use common\models\User;,替换为:use api\models\User;,在前台、后台应用中同样类似处理,如图8
17、在 api 应用中搜索 common\models\User,替换为:api\models\User,在前台、后台应用中同样类似处理,如图9
18、编辑 \common\logics\LoginForm.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 | <?php namespace common\logics; use Yii; use yii\base\Model; /** * Login form */ class LoginForm extends Model { public $username ; public $password ; public $rememberMe = true; private $_user ; /** * {@inheritdoc} */ public function rules() { return [ // username and password are both required [[ 'username' , 'password' ], 'required' ], // rememberMe must be a boolean value [ 'rememberMe' , 'boolean' ], // password is validated by validatePassword() [ 'password' , 'validatePassword' ], ]; } /** * Validates the password. * This method serves as the inline validation for password. * * @param string $attribute the attribute currently being validated * @param array $params the additional name-value pairs given in the rule */ public function validatePassword( $attribute , $params ) { if (! $this ->hasErrors()) { $user = $this ->getUser(); if (! $user || ! $user ->validatePassword( $this ->password)) { $this ->addError( $attribute , 'Incorrect username or password.' ); } } } /** * Logs in a user using the provided username and password. * * @return bool whether the user is logged in successfully */ public function login() { if ( $this ->validate()) { return Yii:: $app ->user->login( $this ->getUser(), $this ->rememberMe ? 3600 * 24 * 30 : 0); } return false; } /** * Finds user by [[username]] * * @return User|null */ protected function getUser() { if ( $this ->_user === null) { $this ->_user = User::findByUsername( $this ->username); } return $this ->_user; } } |
19、新建 \api\models\LoginForm.php,在api/models目录中的MySQL模型文件为业务逻辑相关(仅与api相关),继承至 \common\logics\LoginForm 逻辑层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 11:10 */ namespace api\models; class LoginForm extends \common\logics\LoginForm { } |
20、复制\api\models\LoginForm.php 至 \frontend\models\LoginForm.php、\backend\models\LoginForm.php,调整为各自的命名空间
\frontend\models\LoginForm.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 11:10 */ namespace frontend\models; class LoginForm extends \common\logics\LoginForm { } |
\backend\models\LoginForm.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php /** * Created by PhpStorm. * User: WangQiang * Date: 2018/04/04 * Time: 11:10 */ namespace backend\models; class LoginForm extends \common\logics\LoginForm { } |
21、在 api 应用中搜索 use common\models\LoginForm;,替换为:use api\models\LoginForm;,在前台、后台应用中同样类似处理,如图10
22、在 api 应用中搜索 common\models\LoginForm,替换为:api\models\LoginForm,在前台、后台应用中同样类似处理,如图11
23、在 common 目录中搜索 common\models\User,替换为:common\logics\User,除了 \common\logics\User.php 例外,如图12
24、在 common 目录中搜索 common\models\LoginForm,替换为:common\logics\LoginForm,如图13
25、测试注册功能,打开网址:http://www.github-shuijingwan-yii2-app-advanced.localhost/site/signup ,符合预期,如图14
26、查看数据库,如图15
近期评论