Where are vardefs from Suite Field creation stored?

Where is the vardef file stored for a field created in Studio?

In attempting to answer that question for myself, I used Studio to create a field with an unusual name (wierdname) and then did a Quick Repair and Rebuild

To see where the vardef field definition is stored, I then used

cd {root of SuiteCRM system}
grep -R wierdname .

The response to that was

grep -R wierdname .
./cache/modules/AYU_Projects/language/en_us.lang.php:  'LBL_WIERDNAME' => 'A very wierdname',
./cache/modules/AYU_Projects/AYU_Projectsvardefs.php:    'wierdname_c' =>
./cache/modules/AYU_Projects/AYU_Projectsvardefs.php:      'labelValue' => 'A very wierdname',
./cache/modules/AYU_Projects/AYU_Projectsvardefs.php:      'name' => 'wierdname_c',
./cache/modules/AYU_Projects/AYU_Projectsvardefs.php:      'id' => 'AYU_Projectswierdname_c',
./custom/Extension/modules/AYU_Projects/Ext/Vardefs/_override_sugarfield_wierdname_c.php:$dictionary['AYU_Projects']['fields']['wierdname_c']['inline_edit']='';
./custom/Extension/modules/AYU_Projects/Ext/Vardefs/_override_sugarfield_wierdname_c.php:$dictionary['AYU_Projects']['fields']['wierdname_c']['labelValue']='A very wierdname';
./custom/Extension/modules/AYU_Projects/Ext/Language/_override_en_us.lang.php:$mod_strings['LBL_WIERDNAME'] = 'A very wierdname';
./custom/modules/AYU_Projects/Ext/Vardefs/vardefs.ext.php:$dictionary['AYU_Projects']['fields']['wierdname_c']['inline_edit']='';
./custom/modules/AYU_Projects/Ext/Vardefs/vardefs.ext.php:$dictionary['AYU_Projects']['fields']['wierdname_c']['labelValue']='A very wierdname';
./custom/modules/AYU_Projects/Ext/Language/en_us.lang.ext.php:$mod_strings['LBL_WIERDNAME'] = 'A very wierdname';

If this is the complete list (which it should be, given how grep operates), the actual vardef for the new field is ONLY stored in the cache directory in cache/modules/{module_name}/{modulename}vardefs.php

The customizations for the field (Label, InLineEdit, ā€¦) are stored in the custom/ā€¦ folders, but NOT the actual field definition, which is only stored in the cache directory

    'wierdname_c' =>
    array (
      'inline_edit' => '',
      'labelValue' => 'A very wierdname',
      'required' => false,
      'source' => 'custom_fields',
      'name' => 'wierdname_c',
      'vname' => 'LBL_WIERDNAME',
      'type' => 'varchar',
      'massupdate' => '0',
      'default' => '',
      'no_default' => false,
      'comments' => '',
      'help' => '',
      'importable' => 'true',
      'duplicate_merge' => 'disabled',
      'duplicate_merge_dom_value' => '0',
      'audited' => false,
      'reportable' => true,
      'unified_search' => false,
      'merge_filter' => 'disabled',
      'len' => '255',
      'size' => '20',
      'id' => 'AYU_Projectswierdname_c',
      'custom_module' => 'AYU_Projects',
    ),

I thought a cache folder kept COPIES of information to make it quick to access, but if the above is true, then for SuiteCRM, if the cache folder is ā€œdisturbedā€, the system cannot fully recover since there is nowhere else to get some of the information (like the vardef of a field created in Studio).

I did check other posts in the forum, and there was a very detailed (old but detailed) explanation of the cache directory at

However, according to that post, I should be able to delete most of the contents of the cache/modules/{modulename) directory, so long as I leave alone the cache/modules/emails directory. But if the above is true then there is more at risk that just the cache/modules/emails directory in cache/modules

So maybe I am missing something

Can someone please clarify?

I should have clarified why the above qestion is important

I am trying to use git for version control and many posts say to add the entire cache directory to the .gitignore file.

If I do that, when I commit new changes, any vardefs for fields created in Studio will not be sent to the remote repository so anyone pulling the remote repository will not get the new field defnitions.

Unless, as I said, I am missing something (which has been known to happen ā€¦ )

Thoughts?

When you create a new field from the studio, the field definitions are stored in a database table called ā€œfields_meta_dataā€.

@sagarjaydeep
Thank you, good to know.
But how does SuiteCRM know how to access the field?

If I manually tar the site directory and mysql_dump the database, I can duplicate the installation by installing the tar files and running the mysql .sql file on a new installation.

But if I am using git to manage the version control, how does someone pull my files and re-create the installation?

If I manually create fields using vardefs, a pull from the central repository includes the vardefs in the custom/ā€¦ directory and when someone pulls and then does a Repair and Rebuild, the fields are created in the new installation.

But if the only place in the SuiteCRM directory that fields created in Studio exist is in the cache/ā€¦ directory, then a pull from the central repository will not result in the fields being created in the database or defined in SuiteCRM.

So how do I create an installation of SuiteCRM using git as my central repository and have others pull from the central repository and duplicate the installation?

@Ramblin

Studio is tool for current installation. If you want to use git I recommend creating file(s) in custom directory.

  1. Create file in directory: custom/Extension/modules/<module_name>/Ext/Vardefs/<file_name>.php
    ā€“ It works for all modules (system and custom).
    ā€“ Several fileds can be in one file.
    ā€“ You can redefine parameters of system modules fields.
  2. Write description of field, for an example:
$dictionary["<modile_name>"]["fields"]["number"] = array (
    'required' => true,
    'name' => 'number',
    'vname' => 'LBL_NUMBER',
    'type' => 'int',
    'readonly' => true,
    'len' => 11,
    'auto_increment' => false,
    'massupdate' => 0,
    'no_default' => false,
    'comments' => '',
    'help' => '',
    'importable' => true,
    'duplicate_merge' => 'disabled',
    'duplicate_merge_dom_value' => '0',
    'audited' => false,
    'reportable' => true,
    'unified_search' => false,
    'merge_filter' => 'disabled',
);
  1. Add language file (if need) ā€˜custom/Extension/modules/<modile_name>/Ext/Language/en_us.<any_suffix>.phpā€™
$mod_strings['LBL_NUMBER'] = 'Number';
  1. Run ā€˜Quick Rapair and Rebuildā€™

This is a standard method for SuiteCRM 7.

@p.konetskiy

Unfortunately, that method works for nearly all field types ā€¦ but not for relate fields.
If you add a relate field and the corresponding id field only in custom/Extension/modules/<module_name>/Ext/Vardefs/

  • the id field is not created in the module_cstm table
  • the relate field is not added to the fields_meta_data table,

after Repair / Quick Repair,

so you donā€™t see that field in Studio.
I never found the time to raise that issue on GitHub.

@blqt

It works for ALL field types, including related fields and relationships. I always use it for my projects. The fields are created in the <module_name> table in the database, not in <module_name_cstm> and do not use the ā€˜fields_meta_dataā€™ table.
You can see the files in Studio, but they are not marked with (*).

@blqt @p.konetskiy

Thank you for your feedback

Good to know. Wish I knew this before I created my site. Ah, the disadvantages of being an amateur like me.

As for teh relate field via vardefs ā€¦

I had to add a relate field and matching subpanel via vardefs when I wanted to add a one-to-many relationship from Contacts->Contacts. I created a Fund-Raiser package and I wanted a field like ā€œReports Toā€ where, for each Contact, if we had the information, we would identify who connected a donor to us. The people who were identified by many others as the ā€œconnectionā€ we treated as influencers and gave them special attention.

I could not use Studio to setup a one-to-many within the same module (SuiteCRM choked when I tried this), so did it via vardefs as follows (adjust names, ā€¦ to suit your installation)

Create the new subpanel

mkdir -p custom/modules/Contacts/metadata/subpanels
cp -a modules/Contacts/metadata/subpanels/default.php custom/modules/Contacts/metadata/subpanels/ContactsKCRCSpForContacts.php

In custom/Extension/modules/Contacts/Ext/Vardefs/rotary_contacts_1.php

<?php

$dictionary["Contact"]["relationships"]["contacts_contacts_1"] = array (
	'lhs_module' => 'Contacts',
	'lhs_table' => 'contacts',
	'lhs_key' => 'id',
	'rhs_module' => 'Contacts',
	'rhs_table' => 'contacts',
	'rhs_key' => 'rotary_contact_id',
	'relationship_type' => 'one-to-many',
);
$dictionary['Contact']['fields']['rotary_contacts_1'] = array (
	'name' => 'rotary_contacts_1',
	'type' => 'link',
	'relationship' => 'contacts_contacts_1',
	'side' => 'left',
	'source' => 'non-db',
	'vname' => 'LBL_ROTARY_CONTACT_SUBPANEL',
);
$dictionary['Contact']['fields']['rotary_contacts_1_link'] = array (
	'name' => 'rotary_contacts_1_link',
	'type' => 'link',
	'relationship' => 'contacts_contacts_1',
            'link_type' => 'one',
	'side' => 'right',
	'source' => 'non-db',
	'vname' => 'LBL_CONTACT_RELATE_FIELD',
);
$dictionary['Contact']['fields']['rotary_contact_id'] = array (
	'name' => 'rotary_contact_id',
	'vname' => 'LBL_ROTARY_CONTACT_ID',
	'type' => 'id',
	'reportable' => false,
	'duplicate_merge' => 'disabled',
	'required' => false,
);
$dictionary['Contact']['fields']['primary_rotary_contact'] = array (
	'name' => 'primary_rotary_contact',
	'id_name' => 'rotary_contact_id',
	'type' => 'relate',
	'rname' => 'name',
	'vname' => 'LBL_CONTACT_RELATE_FIELD',
	'link' => 'contacts_contacts_1_link',
	'module' => 'Contacts',
	'source' => 'non-db',
	'dbType' => 'non-db',
	'studio' => 'visible',
            'isnull' => 'true',
	'reportable' => true,
	'importable' => true,
	'inline_edit' => '',
);

in custom/Extension/modules/Contacts/Ext/Layoutdefs/rotary_contact.php

<?php

$layout_defs["Contacts"]["subpanel_setup"]['rotary_contacts_1'] = array (
'order' => 100,
'module' => 'Contacts',
'subpanel_name' => 'ContactsKCRCSpForContacts',
'sort_order' => 'asc',
'sort_by' => 'id',
'title_key' => 'LBL_ROTARY_CONTACT_SUBPANEL',
'get_subpanel_data' => 'rotary_contacts_1',
'top_buttons' =>
array (
/*
0 =>
array (
'widget_class' => 'SubPanelTopButtonQuickCreate',
),
1 =>
array (
'widget_class' => 'SubPanelTopSelectButton',
'mode' => 'MultiSelect',
),
*/
),
);

in custom/Extension/modules/Contacts/Ext/Language/en_us.rc_custom.php

<?php

$mod_strings['LNK_RC_CUSTOM_LIST'] = 'View KCRC Members';
$mod_strings['LNK_RC_CUSTOM_TITLE'] = 'Contacts who are current KCRC members';
$mod_strings['LBL_FUND_ALERT_MSG'] = 'Error Message';
$mod_strings['LBL_CONTACT_RELATE_FIELD'] = 'Primary KCRC Contact';
$mod_strings['LBL_ROTARY_CONTACT_SUBPANEL'] = 'Primary KCRC Contact for these Contacts ';
$mod_strings['LBL_REPORTS_TO'] = "Primary non-KCRC Contact";
$mod_strings['LBL_DIRECT_REPORTS_SUBPANEL_TITLE'] = 'Primary non-KCRC Connection to these Contacts ';

A Quick Repair and Rebuild and it works and is captured by git

I wish I had asked this question earlier; I now have to go back and redefine all the new fields with vardefs, not Studio (sigh ā€¦)

Donā€™t you love whiners like me ? :slight_smile:

OK.
I had defined these fields as custom field ā€¦ which seemed logical to me as they are custom fields.
Iā€™ll try again as non custom fields

@blqt

I have been told that if you are adding fileds to an existing module, best practice is to add them as custom fields - which you can do via vardefs (add via studio, see the definition, delete from studio and add as vardef) - but in some cases, like using Flex Relate, if the field definitions are not in the core (not _cstm) table, it causes complications with some lookups.

In my case for the relate field / subpanel setup for one-to-many for Contacts->Contacts, the Studio option did not work so I just added to the core table via vardefs.

@Ramblin , @blqt
I think for replication Studio isnā€™t a good solution. I create installation zip file for new version of my decisions usually. I understand that it isnā€™t modern solution but it is well compatible with SuiteCRM .

Iā€™m glad if I could help you!

@p.konetskiy
You did help me understand the limitations of SuiteCRM . Thank you.

@blqt

If you are trying to duplicate in vardefs what you used to use Studio to create, you can set you system up to show you what go6t changed when you did something.

Do NOT do this on a Production system since there are performance degradations.

Take a look at a post by @pgr

and give that a shot.

It will show you what files are added when you use Studio to add fields.

Copy those files to a text editor/IDE , delete the field via Studio and manually add the vardef back in using @p.konetskiy directions above.

1 Like

@Ramblin

Actually, we never use studio for customizations except for prototyping or to prepare modules on a development server.
Then we adapt and extend our customizations that we install on preproduction or production servers with GitHub or using Module Loader.
Thatā€™s much easier for documentation and version management

@blqt

I now know that is the best way to do things

Too bad I did not know that before I spent 3 months using Studio - and now have to go back and re-do things ā€¦ :slight_smile:

@sagarjaydeep @p.konetskiy

Can you share your thoughts on the following?

Questions:

  1. How DO you add fields to the _cstm table of a module using vardefs?
  2. Is this what is recommended when adding fields to a core module?

If I create a new field from vardefs, I put entries like what @p.konetskiy showed above into:

  • custom/Extension/modules/{modulename}/Ext/Vardefs
  • custom/Extension/modules/{modulename}/Ext/Language

When I do a Repair and Rebuild, this adds the field definition to the core {modulename} database table, including the VNAME (label) definition.

This works fine for custom modules I have created

However, if I add fields to a core module (say FP_events) and I do the same thing, it adds the field definition to the core (fp_events) database table. I have been told that is bad practice and that if I am adding fields to a core module, I should add them to the moduleā€™s _cstm table. This ensures future updates to the core module/database table will not be in conflict with my updates.

If I wanted to add field definitions to core modules and add them to the _cstm table for the core module (eg fp_events_cstm), if I duplicated the vardef created by studio and put the following into custom/Extension/modules/FP_events/Ext/Vardefs/myCustomField.php

<?php
$dictionary['FP_events']['fields']['wierdname_c'] = array (
      'name' => 'wierdname_c',
      'inline_edit' => '',
      'labelValue' => 'A very wierdname',
      'required' => false,
      'source' => 'custom_fields',
      'vname' => 'LBL_WIERDNAME',
      'type' => 'varchar',
      'massupdate' => '0',
      'default' => '',
      'no_default' => false,
      'comments' => '',
      'help' => '',
      'importable' => 'true',
      'duplicate_merge' => 'disabled',
      'duplicate_merge_dom_value' => '0',
      'audited' => false,
      'reportable' => true,
      'unified_search' => false,
      'merge_filter' => 'disabled',
      'len' => '255',
      'size' => '20',
      'id' => 'FP_eventswierdname_c',
      'custom_module' => 'FP_events',
      'studio' => 'visible',
);

and added the language definition in custom/Extension/modules/FP_events/Ext/Language/en_us.myCustomField.php

<?php
$mod_strings['LBL_WIERDNAME'] = 'A very wierdname';

am I following ā€œbest practiceā€?

Questions:

  1. Is that the best way to add a field to a core module?
    (edit: answer = no since I tried it and nothing was added to the fp_events OR fp_events_cstm tables after a Repair & Rebuild (No Execute was presented))
  2. If I do use the above method, do I also have to manually add/edit an entry in the fields_meta_data table or will the above vardef do that for me after a Repair and Rebuild?
    (edit: answer = something else needs to happen since I tried it and nothing was added to fields_meta_data table after a Repair & Rebuild (No Execute was presented))

OK, so the edits demonstrate my amateur status.

Now the REAL questions:

  1. How DO you add fields to the _cstm table of a module using vardefs?
  2. Is this what is recommended when adding fields to a core module?

Thank you for helping out here. No what I would call newbie question but definitely from an amateur ā€¦ :slight_smile:

This post wonā€™t answer the questions above, but it will suggest a different way of doing things, which sometimes is useful. And it provides a full map of changing fields in files, so in the end it might help you somewhat.

I actually did use that post to help me figure out how to setup the relate field and subanel (see above) for a special application where I had to add a one-to-many relationship Contacts-to-Contacts and trying to link a module to itsef in Studio with a one-to-many relationship did not work. Creating it manually in vardefs (as shown above) did the trick.

But that left all the fields defined in the core (contacts) database table.

I was looking to see how to add fields to the _cstm table using vardefs.

But maybe you could provide your thoughts on the ā€œbest practiceā€ question:

  • When adding fields via vardefs to a core module (FP_Events, Contacts, ā€¦) is it recommended to add fields in the _cstm database table or is it OK to add fields in the core database table.

If adding via the _cstm table is the recommendation, and Studio does not do it in a way that can be shared using a version control system like git, then I am back to the question of:

  • How do you add fields to a _cstm table using vardefs?

@p.konetskiy @pgr @sagarjaydeep

I found instructions at
https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_11.0/Data_Framework/Vardefs/Manually_Creating_Custom_Fields/

that look like they are exactly what I want, but they are missing a rather critical piece of information. Hopefully one of you can fill it in.

In the post linked above, they show two ways of adding fields to the _cstm table :

  1. Recommended: Programatically (NOT via Module Installer) using the ModuleInstaller class with the install_custom_fields() method - found at {SuiteCRM_Root}/ModuleInstall/ModuleInstaller.php line 1272
  2. Using vardefs (numerous caveats with this one)

For using vardefs, the caveats include:

  • NOT defining the $dictionary as an array (like I did above) but instead defining each array element separately
  • Making sure the module into which you are adding a custom field already has a _cstm table
  • Making sure the fields_meta_data table already has an entry for the module

I tried creating individual $dictionary elements instead of using the array and I do have a _cstm table and there is already an entry in fields_meta_data for another custom field in my module.
But the vardef method did not work.

When I look at the instructions for using the install_custom_fields method programatically, it looked pretty clear ā€¦ EXCEPT ā€¦

  • Where to I put the php file they show for accessing the install_custom_fields method?

Can anyone tell me where I put the php file they show in that post?
And how I call it?

@Ramblin

I donā€™t see a problem with adding fields to the moduleā€™s main table. But if you only want to use a custom table, you can add the parameter ā€˜sourceā€™ to the fieldā€™s array.

$dictionary["<modile_name>"]["fields"]["number"] = array (
    'required' => true,
    'name' => 'number',
    'vname' => 'LBL_NUMBER',
    'type' => 'int',
    'readonly' => true,
    'len' => 11,
    'auto_increment' => false,
    'massupdate' => 0,
    'no_default' => false,
    'comments' => '',
    'help' => '',
    'importable' => true,
    'duplicate_merge' => 'disabled',
    'duplicate_merge_dom_value' => '0',
    'audited' => false,
    'reportable' => true,
    'unified_search' => false,
    'merge_filter' => 'disabled',
// add the parameter
    'source' => 'custom_fields'
);