SuiteCRM 全功能,不限用户,3600元/长期使用
SuiteCRM 与 Salesforce 和 Dynamics 一样强大,具有更高的技术独立性和定制性。业务咨询与服务,请联系我们!
我们提供的服务包括:插件开发、主题开发、安装和配置、CRM升级、CRM部署、支持与维护、用户培训…
什么是Vardefs?
Vardef用于向SuiteCRM提供有关特定bean的信息。这些通常指定给定模块中的字段,关系和索引,以及其他信息,例如是否经过审核,表名等。
定义Vardefs
modules
Vardef最初在其各自的modules文件夹中定义。对于“客户”模块,这将在modules/Accounts/ vardefs.php
中。该信息使用模块名称作为键存储在名为$ dictionary
的数组中。对于帐户,这将是$dictionary['Account']
。让我们看看Account vardefs(为简洁起见已对其进行了编辑):
$dictionary['Account'] =
array(
'table' => 'accounts',
'audited'=>true,
'unified_search' => true,
'unified_search_default_enabled' => true,
'duplicate_merge'=>true,
'comment' => 'Accounts are organizations or entities that ...',
'fields' => array (
//Snipped for brevity. See the fields section.
),
'indices' => array (
//Snipped for brevity. See the indices section.
),
'relationships' => array (
//Snipped for brevity. See the relationship section.
),
//This enables optimistic locking for Saves From EditView
'optimistic_locking'=>true,
);
VardefManager::createVardef(
'Accounts',
'Account',
array('default', 'assignable','company',)
);
各键值的解释
以下是可以为vardefs指定的一些键。字段,索引和关系在其各自的部分中介绍。
table
该模块的数据库表名称。
audited
是否应审核此模块。注意audited
还必须在字段级别设置要审核的字段。
unified_search
是否可以通过全局搜索来搜索此模块。
unified_search_default_enabled
默认情况下是否可以通过全局搜索来搜索此模块。
duplicate_merge
是否为此模块启用了重复合并功能。
comment
此模块的说明。
optimistic_locking
是否应该对此模块启用乐观锁。乐观锁通过假设不会发生冲突来锁定记录上的并发编辑。保存后,将检查记录上最后修改的时间戳。如果不同,则自加载该记录以来发生了编辑。如果是这种情况,那么将向用户提示一个页面,其中显示了两个编辑中的差异,并要求用户选择要使用的编辑。
乐观锁(optimistic locking):允许多个人同时修改同一文件。乐观锁基于一个假定:大多数时候,这种并发修改不会引起冲突。
字段
先放个实例代码:
$dictionary['Task'] = array(
'table' => 'tasks',
'unified_search' => true,
'full_text_search' => true,
'fields' => array(
'name' =>
array(
'name' => 'name',
'vname' => 'LBL_SUBJECT',
'dbType' => 'varchar',
'type' => 'name',
'len' => '50',
'unified_search' => true,
'full_text_search' => array('boost' => 3),
'importable' => 'required',
'required' => 'true',
),
'status' =>
array(
'name' => 'status',
'vname' => 'LBL_STATUS',
'type' => 'enum',
'options' => 'task_status_dom',
'len' => 100,
'required' => 'true',
'default' => 'Not Started',
),
'date_due_flag' =>
array(
'name' => 'date_due_flag',
'vname' => 'LBL_DATE_DUE_FLAG',
'type' => 'bool',
'default' => 0,
'group' => 'date_due',
'studio' => false,
),
'date_due' =>
array(
'name' => 'date_due',
'vname' => 'LBL_DUE_DATE',
'type' => 'datetimecombo',
'dbType' => 'datetime',
'group' => 'date_due',
'studio' => array('required' => true, 'no_duplicate' => true),
'enable_range_search' => true,
'options' => 'date_range_search_dom',
),
'time_due' =>
array(
'name' => 'time_due',
'vname' => 'LBL_DUE_TIME',
'type' => 'datetime',
//'db_concat_fields'=> array(0=>'date_due'),
'source' => 'non-db',
'importable' => 'false',
'massupdate' => false,
),
'date_start_flag' =>
array(
'name' => 'date_start_flag',
'vname' => 'LBL_DATE_START_FLAG',
'type' => 'bool',
'group' => 'date_start',
'default' => 0,
'studio' => false,
),
'date_start' =>
array(
'name' => 'date_start',
'vname' => 'LBL_START_DATE',
'type' => 'datetimecombo',
'dbType' => 'datetime',
'group' => 'date_start',
'validation' => array('type' => 'isbefore', 'compareto' => 'date_due', 'blank' => false),
'studio' => array('required' => true, 'no_duplicate' => true),
'enable_range_search' => true,
'options' => 'date_range_search_dom',
),
'parent_type' =>
array(
'name' => 'parent_type',
'vname' => 'LBL_PARENT_TYPE',
'type' => 'parent_type',
'dbType' => 'varchar',
'group' => 'parent_name',
'options' => 'parent_type_display',
'required' => false,
'len' => '255',
'comment' => 'The Sugar object to which the call is related',
'options' => 'parent_type_display',
),
'parent_name' =>
array(
'name' => 'parent_name',
'parent_type' => 'record_type_display',
'type_name' => 'parent_type',
'id_name' => 'parent_id',
'vname' => 'LBL_LIST_RELATED_TO',
'type' => 'parent',
'group' => 'parent_name',
'source' => 'non-db',
'options' => 'parent_type_display',
),
'parent_id' =>
array(
'name' => 'parent_id',
'type' => 'id',
'group' => 'parent_name',
'reportable' => false,
'vname' => 'LBL_PARENT_ID',
),
'contact_id' =>
array(
'name' => 'contact_id',
'type' => 'id',
'group' => 'contact_name',
'reportable' => false,
'vname' => 'LBL_CONTACT_ID',
),
'contact_name' =>
array(
'name' => 'contact_name',
'rname' => 'name',
'db_concat_fields' => array(0 => 'first_name', 1 => 'last_name'),
'source' => 'non-db',
'len' => '510',
'group' => 'contact_name',
'vname' => 'LBL_CONTACT_NAME',
'reportable' => false,
'id_name' => 'contact_id',
'join_name' => 'contacts',
'type' => 'relate',
'module' => 'Contacts',
'link' => 'contacts',
'table' => 'contacts',
),
'contact_phone' =>
array(
'name' => 'contact_phone',
'type' => 'phone',
'source' => 'non-db',
'vname' => 'LBL_CONTACT_PHONE',
'studio' => array('listview' => true)
),
'contact_email' =>
array(
'name' => 'contact_email',
'type' => 'varchar',
'vname' => 'LBL_EMAIL_ADDRESS',
'source' => 'non-db',
'studio' => false
),
'priority' =>
array(
'name' => 'priority',
'vname' => 'LBL_PRIORITY',
'type' => 'enum',
'options' => 'task_priority_dom',
'len' => 100,
'required' => 'true',
),
'contacts' => array(
'name' => 'contacts',
'type' => 'link',
'relationship' => 'contact_tasks',
'source' => 'non-db',
'side' => 'right',
'vname' => 'LBL_CONTACT',
),
'accounts' =>
array(
'name' => 'accounts',
'type' => 'link',
'relationship' => 'account_tasks',
'source' => 'non-db',
'vname' => 'LBL_ACCOUNT',
),
'opportunities' =>
array(
'name' => 'opportunities',
'type' => 'link',
'relationship' => 'opportunity_tasks',
'source' => 'non-db',
'vname' => 'LBL_OPPORTUNITY',
),
'cases' =>
array(
'name' => 'cases',
'type' => 'link',
'relationship' => 'case_tasks',
'source' => 'non-db',
'vname' => 'LBL_CASE',
),
'bugs' =>
array(
'name' => 'bugs',
'type' => 'link',
'relationship' => 'bug_tasks',
'source' => 'non-db',
'vname' => 'LBL_BUGS',
),
'leads' =>
array(
'name' => 'leads',
'type' => 'link',
'relationship' => 'lead_tasks',
'source' => 'non-db',
'vname' => 'LBL_LEADS',
),
'projects' =>
array(
'name' => 'projects',
'type' => 'link',
'relationship' => 'projects_tasks',
'source' => 'non-db',
'vname' => 'LBL_PROJECTS',
),
'project_tasks' =>
array(
'name' => 'project_tasks',
'type' => 'link',
'relationship' => 'project_tasks_tasks',
'source' => 'non-db',
'vname' => 'LBL_PROJECT_TASKS',
),
'aos_contracts' =>
array(
'name' => 'aos_contracts',
'type' => 'link',
'relationship' => 'aos_contracts_tasks',
'source' => 'non-db',
'vname' => 'LBL_CONTRACT',
),
'notes' =>
array(
'name' => 'notes',
'type' => 'link',
'relationship' => 'tasks_notes',
'module' => 'Notes',
'bean_name' => 'Note',
'source' => 'non-db',
'vname' => 'LBL_NOTES',
),
'contact_parent' =>
array(
'name' => 'contact_parent',
'type' => 'link',
'relationship' => 'contact_tasks_parent',
'source' => 'non-db',
'reportable' => false
),
)
,
'relationships' => array(
'tasks_notes' => array(
'lhs_module' => 'Tasks',
'lhs_table' => 'tasks',
'lhs_key' => 'id',
'rhs_module' => 'Notes',
'rhs_table' => 'notes',
'rhs_key' => 'parent_id',
'relationship_type' => 'one-to-many',
),
'tasks_assigned_user' =>
array(
'lhs_module' => 'Users',
'lhs_table' => 'users',
'lhs_key' => 'id',
'rhs_module' => 'Tasks',
'rhs_table' => 'tasks',
'rhs_key' => 'assigned_user_id',
'relationship_type' => 'one-to-many'
)
,
'tasks_modified_user' =>
array(
'lhs_module' => 'Users',
'lhs_table' => 'users',
'lhs_key' => 'id',
'rhs_module' => 'Tasks',
'rhs_table' => 'tasks',
'rhs_key' => 'modified_user_id',
'relationship_type' => 'one-to-many'
)
,
'tasks_created_by' =>
array(
'lhs_module' => 'Users',
'lhs_table' => 'users',
'lhs_key' => 'id',
'rhs_module' => 'Tasks',
'rhs_table' => 'tasks',
'rhs_key' => 'created_by',
'relationship_type' => 'one-to-many'
)
)
,
'indices' => array(
array('name' => 'idx_tsk_name', 'type' => 'index', 'fields' => array('name')),
array('name' => 'idx_task_con_del', 'type' => 'index', 'fields' => array('contact_id', 'deleted')),
array(
'name' => 'idx_task_par_del',
'type' => 'index',
'fields' => array('parent_id', 'parent_type', 'deleted')
),
array('name' => 'idx_task_assigned', 'type' => 'index', 'fields' => array('assigned_user_id')),
array('name' => 'idx_task_status', 'type' => 'index', 'fields' => array('status')),
)
//This enables optimistic locking for Saves From EditView
,
'optimistic_locking' => true,
);
VardefManager::createVardef('Tasks', 'Task', array(
'default',
'assignable',
'security_groups',
));
该字段定义模块中每个字段的行为和属性。
name
字段名称。
vname
用于此字段的语言标签的名称。
type
字段的类型。请参阅字段类型部分。
isnull
是否允许空值
len
如果该字段是字符串类型,则允许的最大字符数。
options
对于枚举字段,此字段的下拉值的语言标签
dbtype
数据库用于存储此字段的类型。这不是必需的,因为通常会选择适当的类型。
default
此字段的默认值。对于date
,datetime
和 datetimecombo
输入您应该使用的字段 display_default
代替。display_default
的默认值date
,datetime
和 datetimecombo
输入字段。样本值:-1 day
,today
,+1 day
, +1 week
, next monday
, first day of the next month
, +1 month
, +1 year
。
massupdate
此字段是否应该可大规模更新。请注意,某些字段类型始终受批量更新限制。
rname
仅适用于相关字段。要从相关模块中获取的字段名称。
id_name
仅适用于相关字段。此bean中包含相关ID的字段。
source
该字段的来源。如果该字段未存储在数据库中,则可以设置为“ non-db”(例如,对于链接字段,由逻辑挂钩或其他方式填充的字段)。
sort_on
对于串联字段(即名称字段),应使用该字段进行排序。
fields
对于串联的字段(即名称字段),应串联一个字段的数组。
db_concat_fields
对于串联的字段(即名称字段),应在数据库中串联的字段数组。通常这与字段相同。
unified_search
如果应通过全局搜索可搜索此字段,则为True。
enable_range_search
列表视图搜索是否应允许对该字段进行范围搜索。这用于日期和数字字段。
studio
该字段是否应在工作室中显示。
audited
是否应审核对此字段的更改。
字段类型
以下是常用的字段类型:
id
一个ID字段。
name
名称字段。这通常是其他字段的串联。
bool
布尔字段。
varchar
可变长度的字符串字段。
char
一个字符字段。
text
文本区域字段。
decimal
十进制字段。
date
日期字段。
datetime
日期和时间字段。
enum
下拉字段。
multienum
一个允许选择多个值的下拉字段。
phone
电话号码字段。
link
通过关系到另一个模块的链接。
relate
一个相关的bean字段。
Indices 数组
Indices数组允许定义该模块的数据库表中应有的任何数据库索引。让我们看一个例子:
'indices' => array (
array(
'name' =>'idx_mymod_id_del',
'type' =>'index',
'fields'=>array('id', 'deleted')),
array(
'name' =>'idx_mymod_parent_id',
'type' =>'index',
'fields'=>array( 'parent_id')),
array(
'name' =>'idx_mymod_parent_id',
'type' =>'unique',
'fields'=>array( 'third_party_id')),
),
每个数组条目至少应具有以下条目:
name
索引名称。数据库通常使用它来引用索引。大多数数据库要求它们是唯一的。
type
要创建的索引的类型。index
只会在字段上添加索引,unique
将在字段上添加唯一约束, primary
将字段添加为主键。
fields
要索引的字段的数组。该数组的顺序将用作索引中字段的顺序。
目前,无法将索引添加到自定义字段。
relationship
Vardef还指定此模块内的关系。这是“客户”模块中的一个经过修改的示例:
'relationships' => array (
'account_cases' => array(
'lhs_module'=> 'Accounts',
'lhs_table'=> 'accounts',
'lhs_key' => 'id',
'rhs_module'=> 'Cases',
'rhs_table'=> 'cases',
'rhs_key' => 'account_id',
'relationship_type' => 'one-to-many'),
),
在这里,我们看到了客户与案例之间的联系。通过以下键指定:
lhs_module
此关系左侧的模块。对于一对多关系,这将是“一个”方面。
lhs_table
左侧模块表。如果不确定模块的表可以在其vardefs中找到。
lhs_key
该链接左侧使用的字段。在这种情况下,它是id
帐户的。
rhs_module
右侧模块。在这种情况下,关系的“许多”方面。
rhs_table
右侧模块表。如前所述,您可以在其vardefs中找到模块表。
rhs_key
右侧使用的字段。在这种情况下account_id
案件领域。
relationship_type
关系的类型-“一对多”或“多对多”。由于这是一对多关系,因此意味着一个客户反馈与一个客户有关,但是一个客户可以有多个客户反馈。
对于多对多关系字段,以下键也可用:
join_table
此关系的联接表的名称。
join_key_lhs
联接表左侧字段的名称。
join_key_rhs
联接表右侧的字段名称。
Vardef模板
Vardef模板提供了用于定义常见vardef的快捷方式。这是通过调用VardefManager::createVardef
并传递模块名称,对象名称和要分配的模板数组。以下是客户vardefs的示例:
VardefManager::createVardef(
'Accounts',
'Account',
array('default', 'assignable','company',)
);
在这个例子中 default
, assignable
和 company
使用模板。以下是一些可用的模板:
basic
default
增加了公共底座字段,诸如id
,name
,date_entered
等
assignable
添加将记录分配给用户所需的字段和关系。
person
添加人员记录共有的字段,例如 first_name
, last_name
,地址等。
company
添加公司常用的字段,例如行业下拉列表,地址等。
自定义vardefs
可以通过将文件添加到其中来定制Vardef
custom/Extension/modules/<TheModule>/Ext/Vardefs/SomeFile.php
然后可以使用此文件来添加新的字段定义或自定义现有的字段定义,例如更改字段类型:
$dictionary["TheModule"]["fields"]["some_field"]['type'] = 'int';
前端
本节仅适用于SuiteCRM 7.11及更高版本。
开发一些复杂的JavaScript功能时,在SUGAR全局变量中包含模块vardefs定义或自定义数据非常有用,因此您可以从JavaScript读取它。
将vardefs.php定义添加到特定视图非常简单:
class AccountsViewEdit extends ViewEdit
{
public function __construct()
{
parent::__construct();
$this->useForSubpanel = true;
$this->useModuleQuickCreateTemplate = true;
$data = $this->getVardefsData('Accounts');
$this->addDomJS($data, 'vardefs');
}
}
之后,您可以轻松地从JavaScript访问vardefs定义
但是我们也可以将其他相关信息添加到SUGAR全局变量中,例如开发人员的数据;-)
class AccountsViewEdit extends ViewEdit
{
public function __construct()
{
parent::__construct();
$this->useForSubpanel = true;
$this->useModuleQuickCreateTemplate = true;
$data = $this->getVardefsData('Accounts');
$this->addDomJS($data, 'vardefs');
$jose = array(
'name' => 'Jose',
'country' => 'Argentina',
'footballTeam' => 'River Plate',
'footballTeamLastTitles' => array(
'Copa Sudamericana 2014',
'Copa Libertadores de América 2015',
'Copa Suruga Bank 2015',
'Recopa Sudamericana 2015',
'Recopa Sudamericana 2016',
'Copa Libertadores de América 2018',
),
);
$this->addDomJS(array($jose), 'developerData');
}
}