前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Yii2用Gii自动生成Module+Model+CRUD

Yii2用Gii自动生成Module+Model+CRUD

作者头像
botkenni
发布2019-09-03 14:41:28
4.5K0
发布2019-09-03 14:41:28
举报
文章被收录于专栏:IT码农

1. 开启gii模块

common/config/main-local.php加入下面代码

代码语言:javascript
复制
return [
    'modules' => [
        'gii'   => [
            'class' => 'yii\gii\Module',
            'allowedIPs' => ['::1','127.0.0.1'], //只允许本地访问gii
            'generators'=> [
            /*重新定义gii model & crud的生成模板*/
            'module'=> [
                'class' => 'yii\gii\generators\module\Generator',
                'templates'=> [
                    'backend'=>'@common/gii/generators/module/default'
                ]
            ],
            'model'=> [
                'class' => 'yii\gii\generators\model\Generator',
                'baseClass'=> 'base\BaseActiveRecord',
                'ns'=> 'common\models',
                'templates'=> [
                    'common'=>'@common/gii/generators/model/default',
                    'backend'=>'@common/gii/generators/model/backend'
                ]
            ],
            'crud'=> [
                'class' => 'yii\gii\generators\crud\Generator',
                'templates'=> [
                    'backend'=>'@common/gii/generators/crud/default'
                ],
                    'baseControllerClass' => 'BaseBackendController',
                    'messageCategory'=> 'backend'
                ]
            ]
        ]
    ]
];

2. 访问gii

URL:http://localhost/项目目录/backend/index.php/gii

3. 生成模块

以后台模块为示例: Module Class 填写要生成module的路径 Module ID 填写模块名 Code Template 选择我们自定义好的Module生成模板

如果生成成功会显示如下:

4. 生成公共模型

生成一个公共模型,方便不同入口应用复用和继承。

生成成功会显示如下:

5. 生成后台私有模型

生成后台私有模型,并继承公共模型,在该类中实现后台私有的方法。

生成成功会显示如下:

6. 生成CRUD操作和视图

去掉用不到的视图文件

生成成功会显示如下:

7. URL访问默认控制器

crud组件common\gii\Crud来实现基础的action

Crud里的index方法已经做好了分页处理。 index视图:backend/modules/test/views/default/index.php 如非必要,不要直接书写原生的SQL

joinWidth方法来关联表,需要在Test类定义好表关联。(注意joinWith里的大小写) 关于关联表的具体用法请参考: http://www.yiichina.com/doc/guide/2.0/db-active-record

backend/modules/test/models/Test.php

代码语言:javascript
复制
    public function getHabitusArticle()
    {
        /**
        * 第一个参数为要关联的字表模型类名称,
        *第二个参数指定 通过子表的 customer_id 去关联主表的 id 字段
        */
        return $this->hasMany(HabitusArticle::className(), ['hid' => 'hid']);
    }

backend/modules/test/controllers/DefaultController.php

代码语言:javascript
复制
    /**
    * 
    * 查询
    */
    public function actionIndex()
    {
        $model = $this->findModel();
        $search_model = new TestSearch;
        $query = $model::find()->select(['*'])->joinWith('habitusArticle')->orderBy('`test`.`hid` asc');
        $query = $search_model->search($query);
        //$query;
        //如果要打印SQL
        //$query = $query->createCommand();
        //echo $query->sql;die;
        echo Yii::$app->crud->index($query, ['model'=> $model]);
    }

得到的SQL:

代码语言:javascript
复制
SELECT * FROM `test` LEFT JOIN `habitus_article` ON `test`.`hid` = `habitus_article`.`hid` ORDER BY `hid`

8. 字段显示值的格式化

先要在modles里定义字段的别名。

backend/modules/test/models/Test.php

代码语言:javascript
复制
    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'hid' => 'Hid',
            'name' => '名称',//定义别名
            'remark' => '描述',//定义别名
            'percent' => 'Percent',//....
            'hearttrait' => 'Hearttrait',
            'common' => 'Common',
            'nacs' => 'Nacs',
            'attack' => 'Attack',
            'listorder' => 'Listorder',
            'datetime' => 'Datetime',
            'status' => 'Status',
            'created_by' => 'Created By',
            'updated_by' => 'Updated By',
        ];
    }

对于字段值重写,只需定义好Model里的attributeFormats()方法来实现字段格式化输出。(非Yii2方法) 如下: 访问index方法时,datetime字段会被格式为"Y-m-d H:i:s"格式, 访问xls方法时,datetime字段会被格式为"Y年m月d日"格式, 匿名函数中的$value表示字段原始值,$data表示select所列出的所有字段值

backend/modules/test/models/Test.php

代码语言:javascript
复制
    /**
     * 字段格式化
    
     */
    public function attributeFormats()
    {
         return [
            'datetime'=>[//字段名
                [
                    'action'=> ['index'],
                    'data'=> function($value, $data){
                        return date("Y-m-d H:i:s", $value); 
                    }
                ],
                [
                    'action'=> ['xls'],
                    'data'=> function($value, $data){
                        return date("Y年m月d日", $value); 
                    }
                ],
            ]
        ];
    }

9. 表单搜索设置

用好yii\db\Query查询构建器包括关联表查询,尽量不要直接写sql语句。 控制器和视图中所用的字典类,获取数据的方法都应写到Model里。

backend/modules/test/models/TestSearch.php中 配置好search方法,根据需求来确定字段搜索是like还是=或者其他。 可参考Yii2的yii\db\QueryandFilterWhere等方法和操作符格式 andFilterWhere可放心使用,搜索时字段非空才会执行。 http://www.yiichina.com/doc/guide/2.0/db-query-builder

backend/modules/test/models/TestSearch.php

代码语言:javascript
复制
public function search($query, $params = [])
{
    $params = $params ? : Yii::$app->request->getQueryParams();
    $this->attributes = $params;

    $start_time = ArrayHelper::getValue($params, 'start_time');//相当于isset($params['start_time']) ? $params['start_time'] : NULL;
    $end_time = ArrayHelper::getValue($params, 'end_time');

    $query->andFilterWhere([
        'status' => $this->status,
    ]);

    $query->andFilterWhere(['like', 'name', $this->name])
        ->andFilterWhere(['like', 'remark', $this->remark])
        ->andFilterWhere(['between', 'datetime', $start_time ? strtotime($start_time.' 00:00') : NULL, $end_time ? strtotime($end_time.' 23:59') : NULL]);
    return $query;
}

得出的sql是:

代码语言:javascript
复制
SELECT * FROM `test` WHERE ((`status`=:qp0) AND (`name` LIKE :qp1)) AND (`datetime` BETWEEN :qp2 AND :qp3) ORDER BY `hid`
  1. 字段排序

backend/modules/test/models/Test.php 需要继承自 base\BaseActiveRecord 定义参与排序的字段:

代码语言:javascript
复制
class Test extends \common\models\test\Test{     
    //排序字段
    public $sortFields = ['percent', 'datetime'];

backend/modules/test/controllers/DefaultController.php

代码语言:javascript
复制
$model = $this->findModel();
$search_model = new TestSearch;
$query = $model::find()->select(['*']);
$query = $search_model->search($query);
$sort = $search_model->sortOrderBy('`test`.`hid` asc');//默认的排序字段
$query->orderBy($sort);

backend\modules\test\views\default_form.php

设置排序链接和样式

代码语言:javascript
复制
<th width="120" class="<?=$model->sortQueryParams('percent', 'class');?>" onClick="window.kk='<?=$model->sortQueryParams('percent', 'link');?>';">占百分比</th>

效果:

  1. 视图及表单,

视图里尽量避免编写复杂的逻辑。

由于默认生成的表单控件都是input, 接下来需要修改createupdate的视图文件(表单)。 按照业务需求设置好字段的表单控件和验证规则

backend\modules\test\views\default_form.php

表单元素为必填项的在lable上的class加上form-required,即:

代码语言:javascript
复制
<label class="col-sm-2 control-label form-required"><?=$model->getAttributeLabel('name');?></label>

常用的表单控件类型有: backend/modules/test/models/Test.php 里定义好了Status的字典

代码语言:javascript
复制
    /**
     * @status
     */
    public static function Status($key = false){
        $array = [
            '0'=> '有效',
            '2'=> '锁定'
        ];
        if ($key === false){
            return $array;
        }else{
            return isset($array[$key]) ? $array[$key] : '';
        }
        
    }

单行文本框:

代码语言:javascript
复制
<?= Html::input('text', 'Test[name]', $model->name, ['class' => 'form-control']) ?>

或者

代码语言:javascript
复制
<?=  Html::activeInput('text', $model, 'name', ['class' => 'form-control']) ?>

多行文本框:

代码语言:javascript
复制
<?= Html::textarea('Test[name]', $model->name, ['class' => 'form-control']) ?>
<?= Html::activeTextarea($model, 'name', ['class' => 'form-control']) ?>

下拉列表:

代码语言:javascript
复制
<?=Html::dropDownList('Test[status]', $model->status, $model::Status(), ['class' => 'form-control m-b']);?>
<?=Html::activeDropDownList($model, 'status', $model::Status(), ['class' => 'form-control m-b']);?>

复选框

代码语言:javascript
复制
<?= Html::checkboxList('Test[status]', $model->status, $model::Status());?>  
<?= Html::activeCheckboxList($model, 'status', $model::Status());?>  

单选框

代码语言:javascript
复制
<?= Html::radioList('Test[status2]', $model->status, $model::Status());?>
<?= Html::activeRadioList($model, 'name', $model::Status()) ?>

单选列表

代码语言:javascript
复制
<?= Html::listBox('Test[status3]', $model->status, $model::Status(), ['class'=>'form-control']);?>
<?= Html::activeListBox($model, 'status', $model::Status(), ['class'=>'form-control']);?>

多选列表

代码语言:javascript
复制
<?= Html::listBox('Test[status4]', $model->status, $model::Status(), ['multiple'=>true, 'class'=>'form-control']);?> 
<?= Html::activeListBox($model, 'status', $model::Status(), ['multiple'=>true, 'class'=>'form-control']);?> 

切换开关

代码语言:javascript
复制
<?= Html::checkbox('Test[status5]', $model->status, ['class'=> 'js-switch']);?> <?= Html::checkbox('HabitusTest[status6]', $model->status, ['class'=> 'js-switch']);?>   
<?= Html::activeCheckboxList($model, 'status', $model::Status(), ['class'=> 'js-switch']);?> 

下拉选择带搜索

代码语言:javascript
复制
<?=Html::dropDownList('Test[status9]', '120000', $model::City(), ['prompt'=>'--请选择--', 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>
<?=Html::activeDropDownList($model, 'status', $model::City(), ['prompt'=>'--请选择--', 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>

下拉多选带搜索

代码语言:javascript
复制
<?=Html::dropDownList('Test[status9]', ['120000','110000'], $model::City(), ['multiple'=>true, 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>
<?=Html::activeDropDownList($model, 'status', $model::City(), ['multiple'=>true, 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>

表单验证规则 示例 更详细的验证方法参考:[jQuery.validate][10] 插件

代码语言:javascript
复制
<script>  
$(function () {        
    $("#view-form-form").validate({
        //debug:true, //如果只调试验证不提交数据,可开启这里
        rules: {
           'Test[name]':{
               required:true,//必填
               maxlength: 50 //最大长度
            },
            //其他的字段的验证...
        },
        ignore:"",//验证包括hidden的input元素
        messages: {
            'Test[name]':{
                required:'请输入体质名称',//未输入提示
                maxlength:'体质名称输入太长'//超出最大长度提示
            },
        }
    });
});
</script>
  1. 保存表单数据到数据库

瘦控制器 胖模型

$model->sava()前会根据Model类的rules()方法定义规则去校验数据

backend/modules/test/models/Test.php

代码语言:javascript
复制
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name'], 'required'],//必填
            [['percent', 'listorder', 'datetime', 'status', 'created_by', 'updated_by'], 'integer'],//必需为数字
            [['name'], 'string', 'max' => 300],//最长300
            [['remark', 'hearttrait', 'common', 'nacs', 'attack'], 'string', 'max' => 500]//字符串,最长500
        ];
    }

guide: 详细的rules 数据验证不通过时可以根据打印$model->getErrors()查看具体错误信息

对于表单提交过来的数据不是最终保存到数据库里的格式时,如时间戳等, 可以通过自定义rules或者重组表单数据来实现:(还有其他方法也可以实现)

backend/modules/test/models/Test.php

代码语言:javascript
复制
    public function validateCountry($attribute, $params)
    {
        $this->$attribute = 'new '.$this->$attribute;//这里可以重新设置name的值
        //也可以使用自定义验证规则
        //if (!in_array($this->$attribute, ['USA', 'Web'])) {
            //$this->addError($attribute, 'The country must be either "USA" or "Web".');
        //}
    }
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['name', 'validateCountry'],
            [['name'], 'required'],
            [['percent', 'listorder', 'datetime', 'status', 'created_by', 'updated_by'], 'integer'],
            [['name'], 'string', 'max' => 300],
            [['remark', 'hearttrait', 'common', 'nacs', 'attack'], 'string', 'max' => 500]
        ];
    }

或者我们用behaviors来实现一些字段的数据的自动化填充

backend/modules/test/models/Test.php

代码语言:javascript
复制
    public function behaviors()
    {
        return [
            [
                'class' => 'yii\behaviors\BlameableBehavior',
                'createdByAttribute' => 'created_by',//create时,created_by字段的值会自动填充为当前操作用户的ID:Yii::$app->user->identity->id;
                'updatedByAttribute' => 'updated_by',
            ],
            'timestamp' => [
                'class' => 'yii\behaviors\TimestampBehavior',
                'attributes' => [
                    //insert数据库前datetime的值会自动填充为当前的时间戳
                    BaseActiveRecord::EVENT_BEFORE_INSERT => ['datetime'],
                    //BaseActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
            ],
        ];
    } 
代码语言:javascript
复制
    public function behaviors()
    {
        return [
            [
                'class' => 'yii\behaviors\BlameableBehavior',
                'createdByAttribute' => 'created_by',//create时,created_by字段的值会自动填充为当前操作用户的ID:Yii::$app->user->identity->id;
                'updatedByAttribute' => 'updated_by',
            ],
            'timestamp' => [
                'class' => 'yii\behaviors\TimestampBehavior',
                'attributes' => [
                    //insert数据库前datetime的值会自动填充为当前的时间戳
                    BaseActiveRecord::EVENT_BEFORE_INSERT => ['datetime'],
                    //BaseActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
            ],
        ];
    } 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 开启gii模块
  • 2. 访问gii
  • 3. 生成模块
  • 4. 生成公共模型
  • 5. 生成后台私有模型
  • 6. 生成CRUD操作和视图
  • 7. URL访问默认控制器
  • 8. 字段显示值的格式化
  • 9. 表单搜索设置
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档