Yii2.0 - 枚举字段声明与数据呈现 [ 技术分享 ]
项目中常遇到枚举类型字段的显示问题,如类型、状态等,这些字段在列表页、详情页以及表单页通常需要特殊处理,增加一个类型或状态,要修改所有的视图,这显然不合理,为解决这个问题,可以对Yii框架进行优化,后续只需维护模型即可,以下是代码实现:
1、修改Yii基础模型类:
yii\base\Model,新增attributeValues方法
/**
* Returns the attribute values.
*
* Attribute values are mainly used for display purpose. For example, given an attribute
* `status`, we can declare a value `Active` when `status` equal 1, which is more user-friendly and can
* be displayed to end users.
*
* Note, in order to inherit values defined in the parent class, a child class needs to
* merge the parent values with child values using functions such as `array_merge()`.
*
* @return array attribute values (name => ['key1'=>'value1','key2'=>'value2'])
* @see generateAttributeValue()
*/
public function attributeValues()
{
return [];
}
2、修改列表页获取数据单元值方法:
yii\grid\DataColumn,修改getDataCellValue方法
/**
* Returns the data cell value.
* @param mixed $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
* @return string the data cell value
*/
public function getDataCellValue($model, $key, $index)
{
if ($this->value !== null) {
if (is_string($this->value)) {
return ArrayHelper::getValue($model, $this->value);
} else {
return call_user_func($this->value, $model, $key, $index, $this);
}
} elseif ($this->attribute !== null) {
$value = ArrayHelper::getValue($model, $this->attribute);
if ($model instanceof Model) {
$attributeValues = $model->attributeValues();
if (!empty($attributeValues) && ArrayHelper::keyExists($this->attribute, $attributeValues) && is_array($attributeValues[$this->attribute]) && ArrayHelper::keyExists($value,$attributeValues[$this->attribute])) {
return $attributeValues[$this->attribute][$value];
} else {
return $value;
}
} else {
return $value;
}
}
return null;
}
3、修改详情页标准化属性方法:
yii\widgets\DetailView,修改normalizeAttributes方法
/**
* Normalizes the attribute specifications.
* @throws InvalidConfigException
*/
protected function normalizeAttributes()
{
if ($this->attributes === null) {
if ($this->model instanceof Model) {
$this->attributes = $this->model->attributes();
} elseif (is_object($this->model)) {
$this->attributes = $this->model instanceof Arrayable ? array_keys($this->model->toArray()) : array_keys(get_object_vars($this->model));
} elseif (is_array($this->model)) {
$this->attributes = array_keys($this->model);
} else {
throw new InvalidConfigException('The "model" property must be either an array or an object.');
}
sort($this->attributes);
}
foreach ($this->attributes as $i => $attribute) {
if (is_string($attribute)) {
if (!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/', $attribute, $matches)) {
throw new InvalidConfigException('The attribute must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
}
$attribute = [
'attribute' => $matches[1],
'format' => isset($matches[3]) ? $matches[3] : 'text',
'label' => isset($matches[5]) ? $matches[5] : null,
];
}
if (!is_array($attribute)) {
throw new InvalidConfigException('The attribute configuration must be an array.');
}
if (isset($attribute['visible']) && !$attribute['visible']) {
unset($this->attributes[$i]);
continue;
}
if (!isset($attribute['format'])) {
$attribute['format'] = 'text';
}
if (isset($attribute['attribute'])) {
$attributeName = $attribute['attribute'];
if (!isset($attribute['label'])) {
$attribute['label'] = $this->model instanceof Model ? $this->model->getAttributeLabel($attributeName) : Inflector::camel2words($attributeName, true);
}
if (!array_key_exists('value', $attribute)) {
$value = ArrayHelper::getValue($this->model, $attributeName);
if ($this->model instanceof Model) {
$attributeValues = $this->model->attributeValues();
if (!empty($attributeValues) && ArrayHelper::keyExists($attribute['attribute'], $attributeValues) && is_array($attributeValues[$attribute['attribute']]) && ArrayHelper::keyExists($value,$attributeValues[$attribute['attribute']])) {
$attribute['value'] = $attributeValues[$attribute['attribute']][$value];
} else {
$attribute['value'] = $value;
}
} else {
$attribute['value'] = $value;
}
}
} elseif (!isset($attribute['label']) || !array_key_exists('value', $attribute)) {
throw new InvalidConfigException('The attribute configuration requires the "attribute" element to determine the value and display label.');
}
$this->attributes[$i] = $attribute;
}
}
4、修改下拉框部件,选项设定
yii\widgets\ActiveField,修改dropDownList方法(checkboxList、listBox、radioList同)
/**
* Renders a drop-down list.
* The selection of the drop-down list is taken from the value of the model attribute.
* @param array $items the option data items. The array keys are option values, and the array values
* are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
* For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
* If you have a list of data models, you may convert them into the format described above using
* [[ArrayHelper::map()]].
*
* Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
* the labels will also be HTML-encoded.
* @param array $options the tag options in terms of name-value pairs.
*
* For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeDropDownList()]].
*
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
*
* @return $this the field object itself.
*/
public function dropDownList($items = [], $options = [])
{
if (empty($items)) {
$attributeValues = $this->model->attributeValues();
if (!empty($attributeValues) && ArrayHelper::keyExists($this->attribute, $attributeValues)) {
$items = $attributeValues[$this->attribute];
}
}
$options = array_merge($this->inputOptions, $options);
$this->adjustLabelFor($options);
$this->parts['{input}'] = Html::activeDropDownList($this->model, $this->attribute, $items, $options);
return $this;
}
现在就可以在业务模型类中添加attributeValues方法,以一个游戏任务类为例:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "{{%task}}".
*
*/
class Task extends yii\db\ActiveRecord
{
/**
* (non-PHPdoc)
* @see \yii\base\Model::attributeValues()
*/
public function attributeValues()
{
return [
'type' => [
'0' => '新手任务',
'1' => '每日任务',
'2' => '活动任务',
],
'status' => [
'0' => '暂停',
'1' => '正常',
],
];
}
}
表单页:
<?= $form->field($model, 'status')->dropDownList() ?>
<?= $form->field($model, 'type')->radioList() ?>
列表页和详情页无需特殊处理。
总结一下:
这么做的好处主要是一点,后续只需要修改模型,提升效率 O(∩_∩)O~~
共 1 条回复
a6297416
注册时间:2016-12-04
最后登录:2017-04-26
在线时长:1小时17分
最后登录:2017-04-26
在线时长:1小时17分
- 粉丝0
- 金钱15
- 威望0
- 积分25