作者:尐邪|2015-4-23 交流探讨
说明:yii2提供了足够解析模型数据的方法,但有时候我们还是需要实现一些自定义的数据格式,如果框架提供的方法不足以满足要求时,除了直接在模板中改写外,其实可以看看框架的源码,为框架增加更多的新方法。前几天在群里看到说,yii2的作者已经转go了,这个框架更新已经不在积极。
如GridView Widget中可以使用匿名方法对模型数据进行自定义格式化处理类似,DetailView Widget也提供了类似的处理方法,只是稍微繁琐一些,查看DetailView源码可以发现:
1. 查看其注释
/**
* @var array|Formatter the formatter used to format model attribute values into displayable texts.
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
* instance. If this property is not set, the "formatter" application component will be used.
*/
public $formatter;
2. 继续跟踪 formatter
if ($this->formatter == null) {
$this->formatter = Yii::$app->getFormatter();
} elseif (is_array($this->formatter)) {
// 注意这行 2
$this->formatter = Yii::createObject($this->formatter);
}
if (!$this->formatter instanceof Formatter) {
// 注意这行 1
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
}
3. 得知自定义,格式化,工具类需要从 Formatter 继承
那具体方法要怎么实现呢,接着看源码
protected function renderAttribute($attribute, $index)
{
if (is_string($this->template)) {
return strtr($this->template, [
'{label}' => $attribute['label'],
// 从此行得知 调用的是 Formatter 类中的 format方法
'{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
]);
} else {
return call_user_func($this->template, $attribute, $index, $this);
}
}
4. 于是我们去 yii\i18n\Formatter 中找对应的 format 方法
public function format($value, $format)
{
if (is_array($format)) {
if (!isset($format[0])) {
throw new InvalidParamException('The $format array must contain at least one element.');
}
$f = $format[0];
$format[0] = $value;
$params = $format;
$format = $f;
} else {
$params = [$value];
}
// 注意这行
$method = 'as' . $format;
if ($this->hasMethod($method)) {
return call_user_func_array([$this, $method], $params);
} else {
throw new InvalidParamException("Unknown format type: $format");
}
}
5. 接着可能就联想到了最常见的 ‘ctime:datetime’ 的格式化方法, 搜索下 asDatetime 就会找到对应的方法了
public function asDatetime($value, $format = null)
{
if ($format === null) {
$format = $this->datetimeFormat;
}
return $this->formatDateTimeValue($value, $format, 'datetime');
}
6. 发现有两个参数,其第一个参数就是解析对应模型属性的值了
到这边,整个流程基本明了,于是乎编辑我们自己的自定义类及格式化方法。
namespace common\louli\vendor;
use yii\helpers\Html;
use yii\i18n\Formatter;
class ImgKeysFormatter extends Formatter
{
public function asKeys2img($value)
{
$tHtml = '';
$keys = explode('|',$value);
$tHtml .= Html::beginTag('div');
foreach($keys as $key) {
$tHtml .= Html::img(\Yii::$app->params['qiniu']['baseurl'].$key.'-ll120png',[
'width'=>60,
'height'=>60,
'style'=>'border-radius:50%;margin:5px;'
]);
}
$tHtml .= Html::endTag('div');
return $tHtml;
}
}
7. 这样我们就有了 keys2img 方法
接下来就是嵌入使用了,多的就不赘述了,请看以下节选的View源码
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'nickname',
'logo:keys2img',// 使用自定义格式化方法
'randnickname',
'randlogo:keys2img:随机头像',// 自定义格式及标签
'handler',
'ctime:datetime',
[
'attribute'=>'ctime',
'value'=>date("Y-m-d H:i:s",$model->ctime)
],
'status',
],
'formatter' => [ // 这边引入我们自定义的类 (包含需要使用的格式化方法)
'class'=>'common\louli\vendor\ImgKeysFormatter',
],
]) ?>