> For the complete documentation index, see [llms.txt](https://sjp.gitbook.io/knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sjp.gitbook.io/knowledge-base/kai-fa/sugarcrm/custom-field-display.md).

# SugarCRM6.5中字段定制显示方法研究

> 作者：James Zhu (<fatindeed@hotmail.com>)
>
> 创建日期：2018-08-31

## 1. customCode

例如，数据库中有一个的字段`weight_c`，值为`70`，期望输出`70 kg`，则仅需修改相关view文件即可。

列表页面：`custom/modules/module_name/metadata/listviewdefs.php`

```php
$listViewDefs[$module_name] = array(
    // ...
    'WEIGHT_C' => array(
        'type' => 'int',
        'default' => true,
        'label' => 'LBL_WEIGHT',
        'width' => '5%',
        'customCode' => '{$WEIGHT_C} kg',
    ),
    // ...
);
```

详情页面：`custom/modules/module_name/metadata/detailviewdefs.php`

```php
$viewdefs[$module_name] = array(
    // ...
    array(
        'name' => 'weight_c',
        'label' => 'LBL_WEIGHT',
        'customCode' => '{$fields.weight_c.value} kg',
    ),
    // ...
);
```

子面板页面？不支持**customCode**。

## 2. 自定义function字段

例如，数据库中有一个的字段`born_c`，值为`1990-01-01`，期望输出计算后的年龄`28`。

首先需要新建一个字段定义文件`custom/Extension/modules/module_name/Ext/Vardefs/sugarfield_age_c.php`，内容如下：

```php
$dictionary['module_name']['fields']['age_c'] = array(
    'name' => 'age_c',
    'vname' => 'LBL_AGE_C',
    'type' => 'function',
    'function_class' => 'module_name_util',
    'function_name' => 'get_age',
    'function_params' => array('born_c'),
    'source' => 'function',
    'reportable' => false,
    'importable' => false,
);
```

`module_name_util`可以随便放个地方，只要在module里`require_once`就可以了。

```php
class module_name_util {
    public static function get_age($born_c) {
        if(empty($born_c)) return '';
        $interval = date_diff(date_create(), date_create($born_c));
        return $interval->format('%y');
    }
}
```

然后，运行 **系统管理 > 修复 > 快速修复和重建** 来重新生成字段定义缓存文件。

列表页面：无法直接使用自定义字段，需要通过 **process\_record** 的 *logic\_hook* 手动触发function后，才可在`listviewdefs.php`中使用。`custom/modules/module_name/logic_hooks.php`文件内容如下：

```php
$hook_version = 1; 
$hook_array = array();
$hook_array['process_record'] = array(); 
$hook_array['process_record'][] = array(1, 'process record', 'custom/modules/module_name/module_name_logic_hook.php','module_name_logic_hook', 'process_record');
```

`custom/modules/module_name/module_name_logic_hook.php`文件内容如下：

```php
class module_name_logic_hook {
    public function process_record($bean, $event, $arguments) {
        $bean->age_c = module_name_util::get_age($bean->born_c);
    }
}
```

`custom/modules/module_name/metadata/listviewdefs.php`文件内容如下：

```php
$listViewDefs[$module_name] = array(
    // ...
    'AGE_C' => array(
        'default' => true,
        'label' => 'LBL_AGE',
        'width' => '5%',
        'sortable' => false, // 非数据库字段无法排序，否则会报错
        'customCode' => '{$AGE_C} years old', // 仍可使用customCode定义输出内容
        'related_fields' => array('born_c'), // 保证当列表也没有born_c时也能正常显示
    ),
    // ...
);
```

详情页面：`custom/modules/module_name/metadata/detailviewdefs.php`

```php
$viewdefs[$module_name] = array(
    // ...
    array(
        'name' => 'age_c',
        'label' => 'LBL_AGE',
        'customCode' => '{$fields.age_c.value} years old', // 仍可使用customCode定义输出内容
    ),
    // ...
);
```

子面板页面：与列表页面类似，也需触发 **process\_record** 的 *logic\_hook*，但是定义文件中无法使用**related\_fields**，且无法使用**customCode**，实现方法如下：

`custom/modules/module_name/metadata/subpanels/relation_name.php`

```php
$subpanel_layout[$module_name] = array(
    // ...
    'age_c' => array(
        'default' => true,
        'vname' => 'LBL_AGE',
        'width' => '5%',
        'sortable' => false, // 非数据库字段无法排序，否则会报错
    ),
    'born_c' => array(
        'usage'=>'query_only'
    ),
    // ...
);
```

## 3. 字段function属性

仍然是`born_c`字段，现在期望输出`1990-01-01 (28)`，这种情况下有一个比较简单的方法。

直接修改`born_c`的字段定义文件`custom/Extension/modules/module_name/Ext/Vardefs/sugarfield_born_c.php`，加入如下配置：

```php
$dictionary['module_name']['fields']['born_c']['function'] = array(
    'name' => 'show_dob_with_age',
    'include' => 'custom/modules/module_name/module_name_util.php', // 如果直接写在module文件里，可不用include
    'returns' => 'html',
    'onListView' => true,
);
```

`show_dob_with_age`方法实现如下：

```php
function show_dob_with_age($focus, $field, $value, $view = 'ListView') {
    if(empty($value)) return '';
    $interval = date_diff(date_create(), date_create($value));
    return $value.' ('.$interval->format('%y').')';
}
```

列表页面、详情页面、子面板页面默认显示function处理后的结果。如支持**customCode**（列表页面、详情页面），则仍可自定义输出内容。

```php
$listViewDefs[$module_name] = array(
    // ...
    'BORN_C' => array(
        'default' => true,
        'label' => 'LBL_BORN',
        'width' => '10%',
        'customCode' => '{$BORN_C}', // 使用customCode后显示原始内容
    ),
    // ...
);
```

**PS: 此方法会影响字段的正常编辑，显示虽然方便了，但是编辑不了了。**

## 4. 自定义SugarField

以上两种方法都有局限性，有没有其它更好的方法呢？那就是自定义 **SugarField** 了。

我们新建一个类型为`DateOfBirthWithAge`的 **SugarField**，需要创建以下3个文件：

`custom/include/SugarFields/Fields/DateOfBirthWithAge/SugarFieldDateOfBirthWithAge.php`文件内容如下：

```php
// 这里继承SugarFieldDatetime，在编辑页面即会出现日期选择器组件
require_once('include/SugarFields/Fields/Datetime/SugarFieldDatetime.php');
class SugarFieldDateOfBirthWithAge extends SugarFieldDatetime {
}
```

`custom/include/SugarFields/Fields/DateOfBirthWithAge/ListView.tpl`文件内容如下：

```
{if $parentFieldArray.$col}
    {$parentFieldArray.$col|date_format:"%b %e, %Y"} ({$parentFieldArray.$col|@show_dob_with_age})
{/if}
```

`custom/include/SugarFields/Fields/DateOfBirthWithAge/DetailView.tpl`文件内容如下：

```
{assign var="born" value={{sugarvar key='value' string=true}} }
{if $born}
    {$born|date_format:"%b %e, %Y"} ({$born|@show_dob_with_age})
{/if}
```

至此，**SugarField**创建完成，接着我们需要在使用的module中进行配置。

`show_dob_with_age`方法仍可以直接写入module文件，再修改`born_c`的字段定义文件`custom/Extension/modules/module_name/Ext/Vardefs/sugarfield_born_c.php`，加入如下配置：

```php
$dictionary['module_name']['fields']['born_c']['custom_type'] = 'DateOfBirthWithAge';
```

现在，不管是列表页面、详情页面、子面板页面，还是编辑页面，都可以正常显示。应该是一个比较完美的方案了。

## 总结

介绍了以上4种方法，在实际开发过程中，还需根据不同需求，使用相应的方法。
