Hi, Habravchane!
I want to talk about the project Agora, which is engaged in our team.
Agora is a platform that allows you to organize the distribution of goods via the Internet. The platform integrates with the distributor's ERP and automates the taking of orders, viewing balances, receiving acts of mutual settlements and much more. The user works in the web interface of the platform and all his actions are reflected in the distributor's ERP.
In the article
“How I wrote the“ draft ”of the B2B system” in the blog of our company, I described some of the problems we encountered while creating our platform. At first, the task did not seem to be difficult for us, smarty was chosen as a template engine on the site side, we did not think about the object model, because wrote single business modules each for their own purposes. For example: catalog, reserve, order, search, finance, etc.
As a result, with the expansion of the initial T.Z. the code became non-scalable and some functions or whole blocks had to be used in several places. The functions were copied and the question arose of redoing everything anew.
When designing the system again, we encountered a number of problems:1. How to generate different sets of objects depending on the specific situation?
These sets of objects should be more or less “transparent” to other components of the system. For example, from 1C, the object “buyer’s order” is given to us, we need to generate the corresponding object in Agora or update its status.
2. How to define the boundaries between classes, especially as they develop along with the system being created?
For example, an order and an invoice are very similar objects. They both contain the articles of goods, quantity, price and VAT. But each object has its own properties and methods. And many enterprises have their own “chips” with these 2 objects. In addition to the standard order, one still has an “order-by-order” order, while the other has invoices that still have “fictitious invoices”, etc.
')
3. How to abstract business logic in objects and separate them from database operations?
For example, one distributor has an order with additional fields in the database, while other such fields do not. If we write direct queries to the database, we need to correct them each time, and this is not convenient.
The questions that arise make us think about pattern design. We will not delve into the definitions and terms. They can be found on the Internet.
Perhaps you think that templates are a powerful way to transfer information, or vice versa, that this is just a “soap bubble” that maliciously “academic” developers use. In our case, template design helps a lot.
What we got in the end (below was a list of some of the main classes that implement the templates on which the platform objects are built):

In general, the main idea is as follows:
- Object classes inherit from the AgoraDomainObject class. The AgoraMapper class (data mapper) interacts with the database.
- The AgoraDomainObjectFactory class generates an object from the mapper.
- Many objects are controlled by the AgoraDeferredCollection / AgoraCollection classes.
- The states of the objects (creation, change, mark for deletion) are monitored by AgoraObjectWatcher.
- The AgoraHelperFactory utility class returns Mapper or Collection.
- The AgoraPersistenceFactory helper class coordinates Domain, Collection, Mapper objects.
- All system parameters (including the description of tables in the database) are stored in ini files and loaded 1 time using the AgoraLoader class.
The diagram below shows the organization of the display of a Product object built on the basis of templates:

As a result, we give third-party developers an API for working with objects. The developer does not need to know which SQL queries to execute and which tables. It is more important to him the fundamental API functions on which he will build his modules.
Here is an example of working with goods:
$ id = array (....); // array id
$ productMapper = new productMapper (); // create mapper
$ productCollection = new productCollection (); // create collection
for ($ i = 0; $ i <count ($ id); $ i ++) {
$ product = $ productMapper-> find ($ id [$ i]); // product search by id
$ productCollection-> add ($ product); // add to collection
}
$ product = $ productMapper-> find (1); // search product number 1
echo $ product-> toJson (); // show in json
echo $ productCollection-> toXML (); // upload XML collectionIn the following articles I will tell you more about the technical implementation of Agora.
To be continued…