# Fields
todo
Fields are a super important configuration part of SCP. Materials Meta Data is stored in fields and therefore one of the first starting points for creating a suitable SCP configuration.
Filters are important
Don't forget to check out Filters as they are important for field configuration as well as for a lot of additional configuration options.
# Create your first field
SCP reads field configuration from the fields config key. Every field needs to have its own unique identifier which
acts as the field name.
So let's assume we want to have a new field to contain the country ownership:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'country' => [
'field' => [
'label' => 'Country',
'type' => 'select'
],
],
];
Looks good so far, it will render a new select field but obviously does not contain any values to pick from. So let's fix that:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'country' => [
'field' => [
'label' => 'Country',
'type' => 'select'
],
'values' => [
[
'filter' => [],
'values' => [
'germany' => [
'name' => 'Germany',
'default' => true
],
'switzerland' => [
'name' => 'Switzerland',
'default' => false
]
]
]
],
],
];
You will now see that SCP will render a list of two Switzerland and Germany to pick from.
But what exactly did happen here?
SCP allows you to add multiple Value Sets for select and tag fields – so you can choose by using
Filter which Values SCP should present to the user as a pick list.
As you know from Filters empty arrays are always treated as a matching filter so the configured value set is always presented to the user.
The default flag tells SCP which value is defined as the default value – so be wise and just set one value as the default
for a field 😄.
Order matters
Showcase Platform uses two techniques when it comes to filterable entries – merging and first match.
For Value Sets SCP uses the first match strategy.
Let's create another field to host the language of the material:
<?php
// CLIENT_CONFIG/config/fields/language.php
return [
'field' => [
'label' => 'Language'
],
'values' => [
[
'filter' => [],
'values' => [
'german' => [
'default' => true,
'name' => 'German',
],
'french' => [
'default' => false,
'name' => 'French'
],
'italian' => [
'default' => false,
'name' => 'Italian'
],
]
]
],
];
Cool, we now have two new Select-Fields for some Meta Data. Did you see that we've created the field
inside a new space: config/fields/language.php and we have omitted the root key language.
As SCP maps down the file structure to configuration keys, the fields data is now set inside
fields.language which is exactly what we want – we just did separate our config a little more
to keep readability.
So we can now move on to dynamic fields.
# Dynamic Fields
The above configuration is good but a bit static. The language fields currently contains all possible languages relevant for our countries, but italian is not really relevant for Germany but for Switzerland. So what's about creating a dependency between those fields:
<?php
// CLIENT_CONFIG/config/fields/language.php
return [
'language' => [
'field' => [
'label' => 'Language'
],
'values' => [
[
'filter' => [
'country' => 'germany'
],
'values' => [
'german' => [
'default' => true,
'name' => 'German',
],
]
],
[
'filter' => [
'country' => 'switzerland'
],
'values' => [
'german' => [
'default' => true,
'name' => 'French'
],
'french' => [
'default' => false,
'name' => 'French'
],
'italian' => [
'default' => false,
'name' => 'Italian'
],
]
]
],
],
];
We have created a new Value set which is only valid for the material has the value switzerland stored
inside the country field. When the user changes the country to Switzerland, SCP will rerender the
possible language values to fit your Filter.
So let's add more magic to this field setup:
<?php
// CLIENT_CONFIG/config/fields/language.php
return [
'language' => [
'field' => [
'label' => 'Language',
'filter' => [
'country' => 'switzerland'
],
],
'values' => [
[
'filter' => [
'country' => 'switzerland'
],
'values' => [
'german' => [
'default' => true,
'name' => 'French'
],
'french' => [
'default' => false,
'name' => 'French'
],
'italian' => [
'default' => false,
'name' => 'Italian'
],
]
]
],
],
];
As german Materials are obviously in German, we decided to just show the language field only if it makes sense.
To let SCP know when it has to reload the relationship between the current Material and the Fields configuration, you
need to change the config for the country field just a little:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'country' => [
'field' => [
'label' => 'Country',
'type' => 'select',
'triggersFieldUpdate' => true,
],
'values' => [
// nothing changed here
],
],
];
Setting triggersFieldUpdate to true will instruct Showcase Platform to reload the configuration for fields
once the value of the given field changes.
Field Defaults
If a field is not actively attached to a Material, the default value of the given field might not be set on its data. So be aware of this whenever you use the materials data anywhere in your configuration.
# Vault Fields
Getting values for your field directly from the "Vault"... easy.
We can use two different type of requests. We can get the data from a vql query or from the picklist.
# VQL
If the field has vault_field configuration it should execute the vql_query every time the cache expires
and return results to your field values.
<?php
// CLIENT_CONFIG/config/fields.php
return [
'product' => [
'field' => [
'label' => 'Product',
'type' => 'select',
'vault_field' => [
[
'filter' => [],
'config' => [
'connection' => 'config.veeva_vault.prod',
'vql_query' => 'SELECT id, name__v FROM product__v',
'value' => 'id',
'label' => 'name__v'
]
]
]
],
],
];
Result of the code above will be something like this, and it will be automatically assigned to your field values:
<?php
array (
'00P000000000601' => ['default' => false, 'name' => '3FLEX'],
'00P000000000G04' => ['default' => false, 'name' => 'SPECTRA'],
'00P000000000J41' => ['default' => false, 'name' => 'ZACRTAN'],
// ...
);
You can have multiple configurations for your field based on the different filters:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'product' => [
'field' => [
'label' => 'Product',
'type' => 'select',
'vault_field' => [
[
'filter' => [
'vault_type' => 'com_vault'
],
'config' => [
'connection' => 'config.com_vault.prod',
'vql_query' => 'SELECT id, name__v FROM product__v',
'value' => 'id',
'label' => 'name__v'
]
],
[
'filter' => [
'vault_type' => 'med_vault'
],
'config' => [
'connection' => 'config.med_vault.prod',
'vql_query' => 'SELECT id, name__v FROM product__v',
'value' => 'id',
'label' => 'name__v'
]
]
]
],
],
];
If you need some values filtering you can always use custom callable for your field values that will do the filtering for you, using material and cached data as parameters:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'product' => [
'field' => [
'label' => 'Product',
'type' => 'select',
'vault_field' => [
[
'filter' => [],
'config' => [
'connection' => 'config.veeva_vault.prod',
'vql_query' => 'SELECT product__cr.id, product__cr.name__v, country__cr.id FROM countryproduct__c'
]
]
]
],
'values' => [
[
'filter' => [],
'values' => function (Material $material, array $data) {
$values = [];
$opu = $material->getField('opu')->getValue();
$countryCode = (string) Mapping::get('vault_opu_country', $opu);
foreach ($data as $product) {
if ($countryCode === $product['country__cr.id']) {
$values[$product['product__cr.id']] = [
'default' => false,
'name' => $product['product__cr.name__v']
];
}
}
return $values;
}
]
]
],
];
In this case you don't have to define value and name option because it will be set by your callable.
If you want to parse vault data that is being returned by vault response before it gets passed to the filtering callback as $dataFromVault, you can use vault_response_parser:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'product' => [
'field' => [
'label' => 'Product',
'type' => 'select',
'vault_field' => [
[
'filter' => [
'!vault_type' => 'medicine_vault'
],
'config' => [
'connection' => 'config.veeva_vault.prod',
'vql_query' => 'SELECT product__cr.id, product__cr.external_id__v, product__cr.name__v, country__cr.id FROM countryproduct__c',
'vault_response_parser' => function (array $dataFromVault): array {
$values = [];
foreach ($dataFromVault as $product) {
$id = $product['product__cr.id'];
$values[$id]['name'] = $product['product__cr.name__v'];
$values[$id]['external_id'] = $product['product__cr.external_id__v'];
$values[$id]['country_id'][] = $product['country__cr.id'];
}
return $values;
}
]
]
]
],
'values' => [
[
'filter' => [],
'values' => function (Material $material, array $dataFromVault) {
$values = [];
$opu = $material->getField('opu')->getValue();
$countryCode = (string) Mapping::get('vault_opu_country', $opu);
foreach ($dataFromVault as $product) {
if (in_array($countryCode, $product['country_id'])) {
$values[$product['external_id']] = [
'default' => false,
'name' => $product['name']
];
}
}
return $values;
}
]
]
],
];
# Vault field config parameters
| Parameter | Description | Mandatory |
|---|---|---|
connection | Connection that will be used on Vault API side | true |
vql_query | Query to execute on Vault API side | true |
value | Value that will be used for field value | false |
label | Label that will be used as field value label | false |
cache_duration | Cache duration, default is 30 days | false |
vault_response_parser | Callback for parsing vault response data | false |
# Picklist
Working with Picklists is almost the same as when working with VQL.
It's also not necessary to have a vault_response_parser. But If you want to parse vault data that is being returned by vault response before it gets passed to the filtering callback as $dataFromVault, you can use vault_response_parser:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'crm_org' => [
'field' => [
'label' => 'CRM Org',
'type' => 'select',
'vault_field' => [
[
'filter' => [],
'config' => [
'connection' => 'config.veeva_vault.prod',
'picklist' => 'crm_org__c',
'vault_response_parser' => static function (array $dataFromVault): array {
$values = [];
if (!empty($dataFromVault['picklistValues'])) {
foreach ($dataFromVault['picklistValues'] as $value) {
$values[$value['label']] = $value;
}
}
return $values;
}
]
]
]
]
]
];
The result of the code above will look like this, after it got parsed:
<?php
[
// ...
'americas__c' => [
'name' => 'americas__c',
'label' => 'Americas'
],
'eu__c' => [
'name' => 'eu__c',
'label' => 'EU'
],
'apac__c' => [
'name' => 'apac__c',
'label' => 'APAC'
],
// ...
];
You can have multiple configurations for your field based on the different filters. Please note that the requested object does not always exist. Also note that not every field is in vault. You can use mixed configuration like this:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'crm_org' => [
'field' => [
'label' => 'CRM Org',
'type' => 'select',
'vault_field' => [
[
'filter' => [],
'config' => [
'connection' => 'config.veeva_vault.prod',
'picklist' => 'crm_org__c',
'vault_response_parser' => static function (array $dataFromVault): array {
$values = [];
if (!empty($dataFromVault['picklistValues'])) {
foreach ($dataFromVault['picklistValues'] as $value) {
$values[$value['label']] = $value;
}
}
return $values;
}
]
]
]
],
'values' => [
[
'filter' => [
'opu' => 'global'
],
'values' => [
'na' => ['default' => true, 'name' => 'N/A'],
]
],
[
'filter' => [
'opu' => [
'argentina',
'bolivia',
'brazil',
// ...
]
],
'values' => static function (Material $material, array $dataFromVault): array {
$values = [];
foreach ($dataFromVault as $crmOrg) {
if ($crmOrg['label'] === 'Americas') {
$values[$crmOrg['name']] = [
'default' => true,
'name' => $crmOrg['label']
];
}
}
return $values;
}
],
// ...
]
]
];
Vault field config parameters
| Parameter | Description | Mandatory |
|---|---|---|
connection | Connection that will be used on Vault API side | true |
picklist | Picklist_name which get requested from the vault | true |
value | Value that will be used for field value | false |
label | Label that will be used as field value label | false |
cache_duration | Cache duration, default is 30 days | false |
vault_response_parser | Callback for parsing vault response data | false |
# Field Validations
Fields are managed by users and validation and rules can help to keep your Metadata as clean as possible. We have a handy example for you:
<?php
// CLIENT_CONFIG/config/fields.php
return [
'name' => [
'field' => [
'conditions' => [
[
'rules' => [
'max' => 100,
],
'message' => 'Material Name must not have more than 100 characters'
]
]
]
],
];
So what happens here? As you can see we did not create a new fields as we are just extending one of the Default Fields here. Instead of creating the full configuration, we've only defined that part of the configuration we want to modify.
We did create a new condition which uses the max rule to allow a maximum of 100 characters for the field and a custom message
to let the user know what happens when he ran into this condition.
Check out the reference for fields for details
# Default Fields
SCP defines a few default fields which are relevant for system use and are commonly used.
| Field | Description |
|---|---|
id | Contains the Material ID and is used for internal reference. |
name | The name of the Material used for easier finding of materials. |
description | The description for the given material. |
created_at | The date of creation for the material. |
status | A materials status (e.g. deployed, in progress, etc.) is handled via this field. |
materialType | A special field containing the reference to the Material Type. |
created_by | Stores the id of the user who has created the Material. |
updated_by | Stores the id of the user who has updated the Material recently. |
← Authorization Filters →