AtroCore represents data as entities, which are object-oriented representations of data. The platform has four types of entities, each with a specific purpose:

  • Base: Standard entities stored in a single database table. Most entities will be of this type.
  • Hierarchy: Entities with a parent-to-child hierarchy, like the Category entity in AtroPim. These are represented by two database tables, with the second table managing the hierarchical structure.
  • Relation: Entities for managing many-to-many relationships.
  • ReferenceData: Simple data entities stored in files (specifically, in the data/reference-data folder) instead of the database. They're designed for quick access and automatic injection into the frontend, like the Locale entity in AtroCore.

Creating a New Entity

Let's walk through creating a new entity named Manufacturer within a module called ExampleModule. The entity will have the following fields and relationships:

  • Fields:
    • name: a string
    • description: a text
    • createdAt: a datetime
    • modifiedAt: a datetime
  • Relationships:
    • products: a one-to-Many relationship with the Product entity from the Core module.
    • brands: a many-to-many relationship with the Brand entity from the AtroPim module.
    • createdBy: a many-to-one relationship with the User entity
    • modifiedBy: a many-to-one relationship with the User entity

To create this entity, you need to set up three key files in your module's Resources/metadata directory:

Learn more about how to create a module here.

scopes/Manufacturer.json

This file defines the overall behavior and options for the entity. We'll set the type to Base since it's a standard entity.

{
    "entity": true,
    "layouts": true,
    "tab": true,
    "acl": true,
    "customizable": true,
    "importable": true,
    "object": true,
    "type": "Base",
    "module": "ExampleModule",
    "hasAssignedUser": true,
    "hasOwner": false,
    "hasTeam": false,
    "hasActive": true
}
Parameter Description
entity Specifies that this scope is for an entity.
layouts If true, the entity's layouts can be modified through the administration panel.
tab If true, the entity will have an access point in the hamburger menu.
acl If true, Access Control List (ACL) permissions will be enforced for this entity.
customizable If true, the entity can be updated from the administration panel.
importable If true, the entity can be imported using the Import module.
type The entity type, which must be Base, Hierarchy, or ReferenceData.
module The module the entity belongs to. Services for the entity will be loaded from this module.
hasAssignedUser If true, it will be possible to assign a user to an entity record.
hasOwner If true, it will be possible to set an owner for an entity record.
hasTeam If true, it will be possible to assign an entity record to a team.

entityDefs/Manufacturer.json

This file describes the entity's fields and relationships in detail. It defines the data types and links for each field.

{
    "fields": {
        "name": {
            "type": "varchar",
            "required": true,
            "trim": true
        },
        "description": {
            "type": "text"
        },
        "logo": {
            "type": "file",
            "fileTypeId": "a_image"
        },
        "products": {
            "type": "linkMultiple"
        },
        "brands": {
            "type": "linkMultiple"
        },
        "createdAt": {
            "type": "datetime",
            "readOnly": true
        },
        "modifiedAt": {
            "type": "datetime",
            "readOnly": true
        },
        "createdBy": {
            "type": "link",
            "readOnly": true,
            "view": "views/fields/user"
        },
        "modifiedBy": {
            "type": "link",
            "readOnly": true,
            "view": "views/fields/user"
        }
    },
    "links": {
        "products": {
            "type": "hasMany",
            "entity": "Product"
        },
        "brands": {
            "type": "hasMany",
            "entity": "Brand",
            "relationName": "BrandManufacturer",
            "foreign": "manufacturers"
        },
        "createdBy": {
            "type": "belongsTo",
            "entity": "User"
        },
        "modifiedBy": {
            "type": "belongsTo",
            "entity": "User"
        }
    }
}

view is used by the frontend for custom view on a field instead of the default one for the given field type.

Since the relationship between Manufacturer and Brand is a many-to-many, you also need to define the inverse relationship on the Brand entity by adding the following to Resources/metadata/entityDefs/Brand.json:

{
    "fields": {
        "manufacturers": {
            "type": "linkMultiple"
        }
    },
    "links": {
        "manufacturers": {
            "type": "hasMany",
            "entity": "Manufacturer",
            "relationName": "BrandManufacturer",
            "foreign": "brands"
        }
    }
}

The relationship between Manufacturer and Product is a one-to-many, you also need to define the inverse relationship on the Product entity by adding the following to Resources/metadata/entityDefs/Proudct.json:

{
    "fields": {
        "manufacturer": {
            "type": "link"
        }
    },
    "links": {
        "manufacturer": {
            "type": "belongsTo",
            "entity": "Manufacturer"
        }
    }
}

clientDefs/Manufacturer.json

This file is used by the frontend to determine how the entity's views should be rendered. The default configuration is generally sufficient.

{
    "controller": "controllers/record",
    "iconClass": "tag"
}

\<br>

Parameter Description
controller Specifies the Backbone.js controller used to render the views. controllers/record is the default and is typically all you'll need.
iconClass The icon used for the entity in the tab menu. You can find available icons in the systemIcons.json file in the Core module.

The PhpStorm plugin AtroCore Toolkit can help you automate the creation of these entity files.

Synchronizing the Database

After creating your entity files, run these commands to synchronize the database with your new metadata.

  1. View the generated SQL queries: php console.php sql diff --show
  2. Apply the changes: php console.php sql diff --run

Your new entity is now ready for use.


Using an Entity

Entities in AtroCore have basic getter and setter methods. You can access and modify field values as shown below:

/** @var \Espo\Core\ORM\EntityManager $entityManager */
$entityManager = $containter->get('entityManager');

/** @var \Atro\Core\Templates\Entities\Base $manufacturer */
$manufacturer = $entityManager->getEntity('Manufacturer');

// Set a value
$manufacturer->set('name', 'Brand name');

// Get a value
$name = $manufacturer->get('name');

Customizing and entity

To add custom functionality, such as a new method, create a new class for your entity. All AtroCore entities are instances of a class in \Atro\Core\Templates\Entities\{type} (where type is Base, Hierarchy, ReferenceData, or Relation).

  1. Create a new file in your module's Entities directory: Entities/Manufacturer.php
  2. Extend the appropriate base class (\Atro\Core\Templates\Entities\Base in this case) and add your custom method.
<?php

namespace ExampleModule\Entities;

use Atro\Core\Templates\Entities\Base;

class Manufacturer extends Base
{
    public function getCapitalizeName(): string
    {
        return ucfirst($this->get('name'));
    }
}

Now, you can use your custom method after retrieving the entity.

/** @var \Example\Entities\Manufacturer $manufacturer */
$manufacturer = $entityManager->getEntity('Manufacturer');

$name = $manufacturer->getCapitalizeName();