发布于 2015-12-10 07:26:08 | 2081 次阅读 | 评论: 0 | 来源: PHPERZ
common/config/main-local.php加入下面代码
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' ] ] ] ] ];URL:http://localhost/项目目录/backend/index.php/gii
以后台模块为示例: Module Class 填写要生成module的路径 Module ID 填写模块名 Code Template 选择我们自定义好的Module生成模板
如果生成成功会显示如下:
生成一个公共模型,方便不同入口应用复用和继承。
生成成功会显示如下:
操作时报错:unable to write ......\Test.php (解决:给写入权限就行了)
生成后台私有模型,并继承公共模型,在该类中实现后台私有的方法。
生成成功会显示如下:
去掉用不到的视图文件
生成成功会显示如下:
用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
public function getHabitusArticle() { /** * 第一个参数为要关联的字表模型类名称, *第二个参数指定 通过子表的 customer_id 去关联主表的 id 字段 */ return $this->hasMany(HabitusArticle::className(), ['hid' => 'hid']); }backend/modules/test/controllers/DefaultController.php
/** * * 查询 */ 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:
SELECT * FROM `test` LEFT JOIN `habitus_article` ON `test`.`hid` = `habitus_article`.`hid` ORDER BY `hid`
先要在modles里定义字段的别名。
backend/modules/test/models/Test.php
/** * @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
/** * 字段格式化 */ 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); } ], ] ]; }
用好yii\db\Query查询构建器包括关联表查询,尽量不要直接写sql语句。 控制器和视图中所用的字典类,获取数据的方法都应写到Model里。
在backend/modules/test/models/TestSearch.php中 配置好search方法,根据需求来确定字段搜索是like还是=或者其他。 可参考Yii2的yii\db\Query的 andFilterWhere等方法和操作符格式 andFilterWhere可放心使用,搜索时字段非空才会执行。 http://www.yiichina.com/doc/guide/2.0/db-query-builder
backend/modules/test/models/TestSearch.php
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是:
SELECT * FROM `test` WHERE ((`status`=:qp0) AND (`name` LIKE :qp1)) AND (`datetime` BETWEEN :qp2 AND :qp3) ORDER BY `hid`backend/modules/test/models/Test.php 需要继承自 base\BaseActiveRecord 定义参与排序的字段:
class Test extends \common\models\test\Test{ //排序字段 public $sortFields = ['percent', 'datetime'];backend/modules/test/controllers/DefaultController.php
$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
设置排序链接和样式
<th width="120" class="<?=$model->sortQueryParams('percent', 'class');?>" onClick="window.location.href='<?=$model->sortQueryParams('percent', 'link');?>';">占百分比</th>效果:
视图里尽量避免编写复杂的逻辑。
由于默认生成的表单控件都是input, 接下来需要修改create和update的视图文件(表单)。 按照业务需求设置好字段的表单控件和验证规则
backend\modules\test\views\default_form.php
表单元素为必填项的在lable上的class加上form-required,即:
<label class="col-sm-2 control-label form-required"><?=$model->getAttributeLabel('name');?></label>
常用的表单控件类型有: backend/modules/test/models/Test.php 里定义好了Status的字典
/** * @status */ public static function Status($key = false){ $array = [ '0'=> '有效', '2'=> '锁定' ]; if ($key === false){ return $array; }else{ return isset($array[$key]) ? $array[$key] : ''; } }单行文本框:
<?= Html::input('text', 'Test[name]', $model->name, ['class' => 'form-control']) ?>或者
<?= Html::activeInput('text', $model, 'name', ['class' => 'form-control']) ?>
多行文本框:
<?= Html::textarea('Test[name]', $model->name, ['class' => 'form-control']) ?>
下拉列表:
<?=Html::dropDownList('Test[status]', $model->status, $model::Status(), ['class' => 'form-control m-b']);?>
复选框
<?= Html::checkboxList('Test[status]', $model->status, $model::Status());?>
单选框
<?= Html::radioList('Test[status2]', $model->status, $model::Status());?>
单选列表
<?= Html::listBox('Test[status3]', $model->status, $model::Status(), ['class'=>'form-control']);?>
多选列表
<?= Html::listBox('Test[status4]', $model->status, $model::Status(), ['multiple'=>true, 'class'=>'form-control']);?>
切换开关
<?= Html::checkbox('Test[status5]', $model->status, ['class'=> 'js-switch']);?> <?= Html::checkbox('HabitusTest[status6]', $model->status, ['class'=> 'js-switch']);?>
下拉选择带搜索
<?=Html::dropDownList('Test[status9]', '120000', $model::City(), ['prompt'=>'--请选择--', 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>
下拉多选带搜索
<?=Html::dropDownList('Test[status9]', ['120000','110000'], $model::City(), ['multiple'=>true, 'data-placeholder'=>'选择省份...', 'class'=>'chosen-select', 'style'=>'width:350px;', 'tabindex'=>'2']);?>
表单验证规则 示例 更详细的验证方法参考:[jQuery.validate][10] 插件
<script> $(function () { $("#view-form-form").validate({ //debug:true, //如果只调试验证不提交数据,可开启这里 rules: { 'Test[name]':{ required:true,//必填 maxlength: 50 //最大长度 }, //其他的字段的验证... }, ignore:"",//验证包括hidden的input元素 messages: { 'Test[name]':{ required:'请输入体质名称',//未输入提示 maxlength:'体质名称输入太长'//超出最大长度提示 }, } }); }); </script>瘦控制器 胖模型
$model->sava()前会根据Model类的rules()方法定义规则去校验数据
backend/modules/test/models/Test.php
/** * @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
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
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'], ], ], ]; }