AtroCore utilizes its own built-in ORM (object-relational mapping) to interact with the database or files (in case of ReferenceData). Create, update, read, delete, restore, delete permanently and search operations are performed via the Repository instance provided by the entity manager instance.
You can get an instance of the Entity Manager using the container or inject it directly.
We will continue to use the entity we create in the section Entity.
Repository
AtroCore use the repository pattern to manage entities, so each entity has it own repository, and every repository extended \Atro\Core\Templates\Repositories{Type} where Type is Base, Hierarchy, Relation or ReferenceData to get a repository
/** @var \Espo\Core\ORM\EntityManager $entityManager */
$entityManager = $containter->get('entityManager');
/** @var \Atro\Core\Templates\Repositories\Base $repository */
$repository = $entityManager->getRepository('Manufacturer');
CRUD operations
Create
/** @var \Espo\Core\ORM\EntityManager $entityManager */
$entityManager = $containter->get('entityManager');
/** @var \Atro\Core\Templates\Entities\Base $manufacturer */
$manufacturer = $entityManager->getRepository('Manufacturer')->get();
//Or
$manufacturer = $entityManager->getEntity('Manufacturer');
// set value
$manufacturer->set('name', 'Manufacturer name');
$entityManager->getRepository('Manufacturer')->save($manufacturer);
// Or
$entityManager->saveEntity($manufacturer);
Read and Update
$entityManager = $containter->get('entityManager');
$manufacturer = $entityManager->getRepository('Manufacturer')->get($id);
// Or
$manufacturer = $entityManager->getEntity('Manufacturer', $id);
$manufacturer->set('name', 'New Manufacturer name');
$entityManager->getRepository('Manufacturer')->save($manufacturer);
// Or
$entityManager->saveEntity($manufacturer);
Delete
$entityManager = $containter->get('entityManager');
$manufacturer = $entityManager->getEntity('Manufacturer', $id);
$entityManager->getRepository('Manufacturer')->remove($entity);
// Or
$entityManager->removeEntity($manufacturer);
Restore
$entityManager = $containter->get('entityManager');
$entityManager->getRepository('Manufacturer')->restore($id);
Delete Permanently
$entityManager = $containter->get('entityManager');
$entityManager->getRepository('Manufacturer')->deleteFromDb($id);
echo $manufacturer->get('name');
// new Manufacturer name
List
$entityManager = $containter->get('entityManager');
$manufacturers = $entityManager->getRepository('Manufacturer')->find();
$manufacturerCount = $entityManager->getRepository('Manufacturer')->count();
Select fields
$entityManager = $containter->get('entityManager');
$manufacturers = $entityManager->getRepository('Manufacturer')->select(['id', 'name'])->find();
Ordered list
$manufacturers = $entityManager->getRepository('Manufacturer')
->limit(0, 10)
->order('createdAt', 'DESC')
->find();
Find the first one
$manufacturers = $entityManager->getRepository('Manufacturer')->findOne();
Finds related entities
$manufacturer = $entityManager->getEntity('Manufacturer', $id);
$relationNames = 'products';
$products = $entityManager->getRepository('Manufacturer')->findRelated($entity, $relationNames);
Querying
Comparison operators
Supported comparison operators are: >
, <
, >=
<=
, =
, !=
.
$stocks = $entityManager->getRepository('Stock')->where(['amount>=' => 150])->find();
When using =
use can omit it.
IN and NOT IN
Here the operators =
, !=
are still used, the value just need to be and array.
$manufacturers = $entityManager->getRepository('Manufacturer')->where(['name' => ['ManufacturerName1', 'ManufacturerName2']]);
$notInManufacturers = $entityManager->getRepository('Manufacturer')->where(['name!=' => ['ManufacturerName1', 'ManufacturerName2']]);
LIKE operators
*
is used for LIKE and !*
for NOT LIKE
$manufacturers = $entityManager->getRepository('Manufacturer')->where(['name*' => '%atrocore%' ]);
OR, AND operators
$opportunityList = $entityManager
->getRepository('Product')
->where([
[
'OR' => [
['status' => 'draft'],
['isActive' => false],
],
'AND' => [
'quantity>' => 100,
'quantity<=' => 999,
],
]
])
->findOne();
Customizing an AtroCore Repository
When developing with AtroCore, you may need to add custom methods to a repository to reuse complex database queries or modify the default behavior of entity interactions.
To create a custom repository for an entity, you need to create a new class in your module's Repositories
directory. This class should extend the appropriate base repository class, which is determined by the entity's type (e.g., Base
, Hierarchy
, ReferenceData
, or Relation
).
For our Manufacturer
entity from the ExampleModule
, the custom repository file would be located at Repositories/Manufacturer.php
.
The class should extend \Atro\Core\Templates\Repositories\Base
, as the Manufacturer
entity is of the Base
type.
<?php
namespace ExampleModule\Repositories;
use Atro\Core\Templates\Repositories\Base;
use Espo\ORM\EntityCollection;
use Espo\ORM\Entity;
class Manufacturer extends Base
{
/**
* Returns all active manufacturers.
*
* @return EntityCollection
*/
public function getActiveManufacturers(): EntityCollection
{
return $this->where(['isActive' => true])->find();
}
/**
* Capitalizes the manufacturer's name before it is saved.
*
* @param Entity $entity
* @param array $options
*/
protected function beforeSave(Entity $entity, array $options = [])
{
$entity->set('name', ucfirst($entity->get('name')));
parent::beforeSave($entity, $options);
}
}
This custom repository now includes two new methods:
getActiveManufacturers()
: A new method to retrieve all active manufacturers using a simplewhere
clause.beforeSave()
: A protected method that overrides the default behavior to capitalize the manufacturer's name before the entity is saved to the database. This allows you to apply consistent data formatting. There are more method likeafterSave
,beforeRemove
,afterRemove
,beforeRestore
,afterRestore
,...
Using the Custom Repository
Once the custom repository is created, you can access it through the EntityManager
and call your new methods.
/** @var \Espo\Core\ORM\EntityManager $entityManager */
$entityManager = $containter->get('entityManager');
/** @var \ExampleModule\Repositories\Manufacturer $repository */
$repository = $entityManager->getRepository('Manufacturer');
$activeManufacturers = $repository->getActiveManufacturers();
Using a low level Connection instance:
/** @var \Espo\Core\ORM\EntityManager $entityManager */
$entityManager = $containter->get('entityManager');
/** @var \Doctrine\DBAL\Connection $connection */
$connection = $entityManager->getConnection();
$activeManufacturers = $connection->createQueryBuilder()
->from($connection->quoteIdentifier('manufacturer'))
->select('id, name')
->where('deleted = :false')
->andWhere('isActive = :true')
->setParameter('false', false, \Doctrine\DBAL\ParameterType::BOOLEAN)
->setParameter('true', true, \Doctrine\DBAL\ParameterType::BOOLEAN)
->fetchAllAssociative();
Conclusion
The entityManager
in AtroCore is used to manage entities, but its built-in repository for querying entities has limitations, especially when it comes to querying on related fields.
For more advanced or complex queries that involve relational data, you need to use the SelectManager
. This tool provides more powerful querying capabilities beyond what the standard repository offers.
You can learn more about how to perform complex queries with the SelectManager
in the Advanced data querying section.