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 theCategory
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 thedata/reference-data
folder) instead of the database. They're designed for quick access and automatic injection into the frontend, like theLocale
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
: astring
description
: atext
createdAt
: a datetimemodifiedAt
: a datetime
- Relationships:
products
: a one-to-Many relationship with theProduct
entity from the Core module.brands
: a many-to-many relationship with theBrand
entity from the AtroPim module.createdBy
: a many-to-one relationship with theUser
entitymodifiedBy
: a many-to-one relationship with theUser
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.
- View the generated SQL queries:
php console.php sql diff --show
- 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
).
- Create a new file in your module's
Entities
directory:Entities/Manufacturer.php
- 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();