Metadata Fields in EspoCRM

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • czcpf
    Senior Member
    • Aug 2022
    • 160

    Metadata Fields in EspoCRM

    Hello,

    yuri espocrm espo-dev​​, Thank you and your team for all the work done in rolling out v7.2.

    Discussion/Request:

    Regarding, Espo\Resources\metadata\fields\{fieldType}.json

    Can you please provide more information about the definitions skipOrmDefs, valueFactoryClassName and attributeExtractorClassName​​.

    The Field Metadata documentation only states:

    skipOrmDefs

    true | false

    Skip convert in ORM.

    skipOrmDefs is sometimes set true, other times false, and in some cases, not defined.​ (See Examples below).

    The Field Metadata documentation​ also doesn't mention the definitions valueFactoryClassName and attributeExtractorClassName which are settings described in ORM Value Object documentation as of v7.0+.​

    Similarly, valueFactoryClassName and attributeExtractorClassName are sometimes defined and other times not defined.​ (See Examples below).

    Questions:

    Regarding Espo\Resources\metadata\fields\{fieldType}.json​​​
    1. For developers wanting to create custom fields, when is it appropriate to set skipOrmDefs: true ​​?
    2. If skipOrmDefs is true, what are the implications? Do we also need to create and define custom valueFactoryClassName and attributeExtractorClassName for the field to work correctly ?
    3. If skipOrmDefs​ is (not defined), does it default to false ?
    4. If valueFactoryClassName and attributeExtractorClassName​ are (not defined), do they default to Espo\ORM\Value\ValueFactory and Espo\ORM\Value\AttributeExtractor​ respectively?
    Examples:

    Example 1

    Field:
    address
    Scenario: skipOrmDefs: true​, valueFactoryClassName, attributeExtractorClassName are defined.​
    Espo/Resources/metadata/fields/address.json
    Code:
    {
        ...
        "notMergeable": true,
        "notCreatable": false,
        "filter": true,
        "skipOrmDefs": true,
        "personalData": true,
        "valueFactoryClassName": "Espo\\Core\\Field\\Address\\AddressFactory",
        "attributeExtractorClassName": "Espo\\Core\\Field\\Address\\AddressAttributeExtractor"​
        ...
    }
    Example 2

    Field:
    personName
    Scenario: skipOrmDefs: false, valueFactoryClassName, attributeExtractorClassName are defined​​.​​
    Espo/Resources/metadata/fields/personName.json
    Code:
    {
        ...
        "naming": "prefix",
        "notMergeable": true,
        "notCreatable": true,
        "filter": true,
        "skipOrmDefs": false,
        "personalData": true,
        "textFilter": true,
        "fullTextSearch": true,
        "validationList": [
            "required"
        ],
        "fullTextSearchColumnList": [
            "first",
            "last"
        ]​
    ...
    }
    Example 3

    Field:
    currency
    Scenario: skipOrmDefs: not defined, valueFactoryClassName, attributeExtractorClassName are defined​​.​
    Espo/Resources/metadata/fields/currency.json
    Code:
    {
        ...
        "filter": true,
        "personalData": true,
        "valueFactoryClassName": "Espo\\Core\\Field\\Currency\\CurrencyFactory" ,
        "attributeExtractorClassName": "Espo\\Core\\Field\\Currency\\CurrencyAttributeExtractor"
        ...
    }
  • arkadywtf
    Junior Member
    • Sep 2021
    • 5

    #2
    Hi, so skipOrmDefs means the actual field wont be created in the database. I'll try to explain how's it different from notStorable field using Address Field as an example.

    Let's say you want to add a Billing Address. After adding the address field to your entity you're actually getting 6 new field defs in entityDefs and 5 new columns in the database:
    1. billingAddress (skipped)
    2. billingAddressStreet -> billing_address_street
    3. billingAddressCity -> billing_address_city
    4. billingAddressState -> billing_address_state
    5. billingAddressCountry -> billing_address_country
    6. billingAddressPostalCode -> billing_address_postal_code
    So if you were to unset skipOrmDefs then Espo would create an additional column in the database: billing_address. If you decided to set billingAddress as notStorable then the field would not load in UI as a combined field and you'd need to set street, city, state, country, postal code as individual fields in Layout Manager which would result in poorer UX.

    So let's go to question 2:
    Do we also need to create and define custom valueFactoryClassName and attributeExtractorClassName for the field to work correctly ?
    It seems that currently it's not the case. Those classes seems to be part of a DTO pattern: Coding rules - EspoCRM Documentation​. Instead of using:
    Code:
    $account->get('billingAddressStreet')
    you shoud use
    Code:
    $account->getBillingAddress()
    which will return an Address object. You can even chain methods:
    Code:
    $account->getBillingAddress()->getStreet()
    Above is being done by valueFactoryClassName, while attributeExtractorClassName is used by setValueObject method. Instead of doing:
    Code:
    $account->set('billingAddressStreet', 'Clay Street')
    you should do:
    PHP Code:
    $address = Espo\Core\Field\Address::createBuilder()
        ->setStreet($street)
        ->setCity($city)
        ->setState($state)
        ->setCountry($country)
        ->setPostalCode($postalCode)
        ->build();

    or when you need to change one of the values:
    PHP Code:
    $address = $account->getBillingAddress()->withStreet('Clay Street'); 
    

    then you can pass it to setBillingAddress as such:
    PHP Code:
    $account->setBillingAddress($address);

    If skipOrmDefs​ is (not defined), does it default to false ?
    As you can see here in the code, "skipOrmDefs": false is the same as empty, so it could be removed from Espo/Resources/metadata/fields/personName.json and the result would be the same.


    If valueFactoryClassName and attributeExtractorClassName​ are (not defined), do they default to Espo\ORM\Value\ValueFactory and Espo\ORM\Value\AttributeExtractor​ respectively?
    Seems to be the case. If they are not defined you won't be able to use "getValueObject" and "setValueObject" the way they are being used right now by for example getBillingAddress and setBillingAddress methods.

    I'm not an original dev, so take it as my observations so far. I bet Espo team have more to say about that.
    Last edited by arkadywtf; 10-28-2022, 10:03 AM.

    Comment


    • esforim
      esforim commented
      Editing a comment
      Will add it telecastg . Added this hopefully the name is correct: 58. Metadata Fields in EspoCRM (skipOrmDefs) - https://forum.espocrm.com/forum/deve...lds-in-espocrm

      With @.yuri I think don't he like being ping like this. espocrm is a dead account so don't bother. espo-dev is probably just another use like me, his name a bit misleading.

    • czcpf
      czcpf commented
      Editing a comment
      Thank you arkadywtf for the awesome explanation! Is esforim the general handle to ping developers in the future?

    • esforim
      esforim commented
      Editing a comment
      czcpf no lol, I'm not a developers. for your reference. "user like me".

      I think EspoCRM hire a few more Developers, I seen them around on forum but haven't interact yet.

      But from reading thread, Yuri don't like to ping for unnecessary thing especially Help question. If it a technical development question he might entertain it. If it an actual bug report he will fix it. If it feedback good or bad he go stress mode.
Working...