Entities; The Beating Heart

Introduction

Xua can be configured to communicate with a database server (usually MySQL), but the programmer must specify the database structure. To do so, Xua offers Entity Blocks. Read Entities section under Units chapter for theoretical explanations. In this chapter, we focus on practical details of defining and using entities.

Effects on the projects

Xua will generate a PHP class extending a Xua abstract class called Entity for each Entity Block the programmer creates. These Entity classes are in a one-to-one correspondence with database tables, and each row of the table can be corresponded by an instance of the table's corresponding class.
Also, the same happens in the Marshal Library with respect to the language. However, the front-end clone of the entities only contains method signatures, and the bodies are just network calls.

Server Project Side

A Literal Name is a literal string containing only alphanumeric characters, starting with a lowercase character. The set of all Literal Names is shown by $\mathbb{L}$.
The set of all values possible to store in a variable is shown by $\mathbb{X}$.
A Dictionary is a partial function $D: \mathbb{L} \to \mathbb{X}$ and is usually expressed by all of its records. The set of all dictionaries is shown by $\mathbb{D}$.
A Field $(T, D)$ is a tuple, where $T \in \mathbb{T}$ is a type (described in Supers chapter) called Field Type and $D \in \mathbb{X}$ is a value called Field Default Value (providing $D$ is optional). Note that if $D$ is provided, it is mandatory that $D: T$.
An Entity Signature is a dictionary $F$ such that $F(s) = (T_s, D_s)$ or $F(s)$ is undefined, where $s$ is a Field Name. Domain of the $F$ is called the Set of Field Names of the Entity Signature.
The set $\{ \mathsf{ASC}, \mathsf{DESC} \}$ is called the set of all Order Indicators and is shown by $\mathbb{O}$.
An Index is a $k$-tuple of tuples $(f, o)$ with an extra boolean determining if the index is unique, where $f$ is a Field Name, and $o \in \mathbb{O}$ is an Order Indicator. Indexes are used in the MySQL engine for faster select queries. We try to have a simple explanation here. Let $i_0 = \Big( \big( (f_0, o_0), \dots, (f_n, o_n) \big), u \Big)$ be an Index. Intuitively speaking, The MySQL engine will create a list of pointers to data rows, sorted by the mentioned field, which makes it faster to search on those fields. Also if the Index is marked as unique, i.e., $u = \mathsf{1}$, the combination of fields must be unique in data, i.e., we cannot have two rows with same value of $f_0$, same value of $f_1$, ..., and same value of $f_n$ at the same time.
An Entity Indexes is a set of indexes $I$.
An Entity Validation is a function with no output that inputs a data row and checks if the data is valid. In case of invalid data, an exception is thrown. For example, assume we store data about some events, each event has two fields, start_time and end_time, and the start must be sooner than the end. The Entity Validation checks if this condition holds, and if the end is sooner than the start, it will throw an EntityFieldException.
An Entity Class is a triplet $(F, I, V)$ of fields, indexes, and the validation function.
An Entity Instance is an instance of an entity class, which contains actual values for entity fields.

MySQL Side

A database is a set of tables; each table has a structure consisting of columns, and a set of rows as data.
insert is the action of adding new rows to a table.
select is the action of retrieving table rows on some specific conditions.
update is the action of modifying some table rows on some specific conditions.
delete is the action of removing some table rows on some specific conditions.

Correspondence

Each table is in one-to-one correspondence with an Entity Class. Methods of these classes can communicate with the database server to select, insert, update, and delete data. Fields of the entity class represent the columns of the table, and instances of the class represent the rows of the table.

Structure

An entity block has the following structure.
# Path\To\Entity\EntityName
 
# Description of what this Entity is all about, probably in markdown formatting.
 
Entity [extends Path\To\Another\Entity\EntityName] {
    fields {
        field0 : type0 [= DEFAULT_0]; # Description of field0
        ...                         ; # ...
        fieldN : typeN [= DEFAULT_0]; # Description of fieldN
    }
    [ indexes : {
        ([-]filedName00, ..., [-]fieldName0K)[*]; # Description of index number 0
        ...                                     ; # ...
        ([-]filedNameM0, ..., [-]fieldNameML)[*]; # Description of index number M
    } ]
    [ validation : { VALIDATION_BODY } ]
    [ override<METHOD_NAME_0> { METHOD_0_BODY } ]
    ...
    [ override<METHOD_NAME_P> { METHOD_P_BODY } ]
}
Note that there is no name for the Entity. An Entity name is its file path. Each file can contain at most one block, and the block inherits its name from the file. It is a good practice to have a comment in the first line of the file describing where the file is located.
Note. All entities have a read-only field called id, of its own type Identifier(), defined implicitly. The field id is used in some underlying Xua codes and cannot be removed.

Fields

Each Entity represents a class and is responsible for storing properties of its instances as data in the database. The object (instance) can have different properties, each with its type and default value. These properties are called fields and should be defined with their type and default value in the fields part.

Indexes

An index is a list of fields along with a boolean determining if the index is unique. Indexes are used in the database engine for faster select queries. All fields are assumed to be ascending by default unless the programmer specifies one as descending by a - sign before it, which tells the database engine to sort that field in descending order. A * sign at the end of an index definition makes it a unique index. If the index is marked as unique, the combination of fields must be unique in data. Note that the implicit field id is a unique field by default.

Validation

The body of the validation block is written in pure PHP.
The validation block is responsible for checking if an instance of the Entity is valid, and in case of invalid data, an EntityFieldException must be thrown. For example, assume we have a table of restaurants in an entity called Restaurant. This Entity has two fields, title and active. The title field is unique, but it is impossible to mark it as a unique index in indexes because we may have many inactive records sharing the same title, and the title is unique among the active restaurants. (There is a workaround here to solve this problem only using indexes, but for the purpose of this documentation, we assume there is not.) We can check this in the validation block and throw an EntityFieldException if the title is duplicate.

Overriding Methods

Xua generates a PHP class from each entity, extending Entity. This class have many methods which are possible to override. Here is a list of these methods, with the PHP method that is actually being overridden.
Override<initialize>   => protected static _initialize();
Override<getOne>       => protected static _getOne(Condition $condition, Order $order, string $caller);
Override<store>        => protected _store(string $caller);
Override<storeQueries> => protected _storeQueries(string $caller);
Override<delete>       => protected _delete(string $caller);
Override<getMany>      => protected static _getMany(Condition $condition, Order $order, Pager $pager, string $caller);
Override<countMany>    => protected static _countMany(Condition $condition, Order $order, Pager $pager, string $caller);
Override<deleteMany>   => protected static _deleteMany(Condition $condition, Order $order, Pager $pager, string $caller);
Override<setMany>      => protected static _setMany(array $changes, Condition $condition, Order $order, Pager $pager, string $caller);
Xua provides final methods that include the actual logic, which one can use when overriding a method. Here is a list of these method names.
Name in .xua file Original Method
<initialize> _x_initialize
<getOne> _x_getOne
<store> _x_store
<storeQueries> _x_storeQueries
<delete> _x_delete
<getMany> _x_getMany
<countMany> _x_countMany
<deleteMany> _x_deleteMany
<setMany> _x_setMany
So, as an example, one can override the storeQueries procedure like this.
Override<storeQueries> {
    if (isset(static::fieldSignatures()['updatedAt'])) {
        $this->updatedAt = DateTimeService::now();
    }
    try {
        $return = static::_x_storeQueries(); // original Xua's store Queries logic
        LogService::logDatabaseChange($this);
    } catch (Exception as $e) {
        LogService::logDatabaseException($e);
    }
    return $return;
}
Usually, the original methods suffice, and there is no need to override them, but in case of necessity, be careful not to corrupt the functionality.

Hierarchy

Entities can come in a hierarchy just like PHP classes, and the validation block is a class method.
protected function _validation();
Also, the fields and indexes of a child entity override the ones in the parent. This override includes the type and default value. Also, it is possible to add new fields or indexes to the type, but it is not possible to remove existing fields. Read Examples for more details.

Visibility

The visibility of entities is controlled by overriding methods. There is an additional variable accessible in all methods, including validation, called $caller. This variable contains a string telling what party called this method. The values are accessible as class constants in the class \Xua\Tools\Visibility. These values are Visibility::CALLER_PHP, Visibility::CALLER_DART, etc.
So it is possible to block foreign callers like the following.
if ($caller != Visibility::CALLER_PHP) {
    throw AccessForbiddenException();
}
But there is more than this. It is possible to customize procedures according to the caller. For example
if ($caller != Visibility::CALLER_PHP) {
    if ($this->id) {
        if (!UserService::hasAccess(AccessService::MODIFY_SOME_ENTITY)) {
            throw AccessForbiddenException();
        }
    } else
        if (!UserService::hasAccess(AccessService::CREATE_SOME_ENTITY)) {
            throw AccessForbiddenException();
        }
    }
}
$this->updatedByCaller = $caller;
Note. Accessing The entities through URPI is disabled by default, and therefore the $caller is always PHP. One can enable this feature, but they must be super careful since it may result in severe vulnerabilities.

Special Field Types

In addition to defined supers that can be called to generate type for field types, Xua offers two categories of unusual types that make the development of a project significantly easier and faster and the resulting project more efficient and more secure. Here we try to cover these two outstanding features of Xua.

Virtual Field Supers

In some cases, one needs some fields for an entity that does not contain new data, so if defined as regular fields, this will result in duplicate/not-synced data. These supers will help mix up other fields and generate a new field that is calculated each time called but not stored. There are two types of virtual supers. One is calculated by the PHP engine and the other by the database engine. The Database Virtual Field is used when the programmer wants to use the result in a query, e.g., using in condition or order, while the PHP Virtual Field is used for more complicated mixtures of fields.

PHP Virtual Field

The PHP Virtual Field has the following signature.
PHPVirtualField{
    arguments {
        getter: Callback(
            nullable = false,
            parameters = [
                {
                    name:            null,
                    type:            @php(Entity::class),
                    allowSubtype:    true,
                    required:        true,
                    checkDefault:    false,
                    default:         null,
                    passByReference: false,
                },
            ]
        );
        setter: Callback(
            nullable = true,
            parameters = [
                {
                    name:            null,
                    type:            @php(Entity::class),
                    allowSubtype:    true,
                    required:        true,
                    checkDefault:    false,
                    default:         null,
                    passByReference: true,
                },
                {
                    name:            null,
                    type:            null,
                    allowSubtype:    true,
                    required:        true,
                    checkDefault:    false,
                    default:         null,
                    passByReference: false,
                },
            ]
        ) = null;
    }
    ...
}
PHP Virtual Field Example
Let us say we have fields gender, firstName, and lastName in entity User, and want to create a field called title based on these fields. We can define it like this.
title : PHPVirtualField (
    getter = (User $user) => {
        if ($user->gender == User::GENDER_MALE) {
            $honorific = "Mr ";
        } elseif ($user->gender == self::GENDER_FEMALE) {
            $honorific = "Miss ";
        } else {
            $honorific = "";
        }
        return $honorific . $user->firstName . " " . $user->lastName;
    }
);

Database Virtual Field

The Database Virtual Field has the following signature.
DatabaseVirtualField{
    arguments {
        getter: Callback(
            nullable = false,
            parameters = [
                {
                    name:            null,
                    type:            @php(Entity::class),
                    allowSubtype:    true,
                    required:        true,
                    checkDefault:    false,
                    default:         null,
                    passByReference: false,
                },
                {
                    name:            'params',
                    type:            'array',
                    allowSubtype:    true,
                    required:        true,
                    checkDefault:    false,
                    default:         null,
                    passByReference: false,
                },
            ]
        );
    }
    ...
}
Note that one cannot set a database virtual field, and therefore there is no setter method available on this field.
Note that another method argument is available called params, which is used to pass some extra parameters into the getter method. We discuss it in more detail in the Example section.
Database Virtual Field Example
Let us say that we have an entity called City, and we need a field that tells if the city is a town or a big city. At the moment, we consider cities that have a population of less than a million to be town, but this might change; either the population may change, or we may think of the area as an item, or we can have a more complicated way that involves both population and area of a city. So we cannot calculate the field isTown each time we need it somewhere (this may result in duplicate code). Instead, we need a field that does this so we can change it later and the change affect all usages. We can do this by defining the field isTown this way.
isTown : DatabaseVirtualField (
    getter (City $city, array $params) => {
        return "{Entity::F(self::_POPULATION)->name} < 1000000";
    }
)
For a more complex example, consider this scenario. Let us say that we have an entity called Restaurant, and we want to sort the restaurants by distance in ascending order, so we need a field called distance. A PHP Virtual Field can do this, but in that case, we need to fetch all restaurants from the database server and then sort them, which takes a significant amount of time and space. Instead, we can define it as a Database Virtual Field that allows us to use it while creating an order expression and tell the database server to sort the restaurants by itself and give us the first page. We define this field using the following code.
distance : DatabaseVirtualField (
    getter (City $city, array $params) => {
        here = $params['here']; # Here, one can understand the application of the params argument.
        $lat0 = "(PI() * {$here->lat} / 180)";
        $long0 = "(PI() * {$here->long} / 180)";
        $lat1 = "(PI() * {Entity::F(self::_GEO_LAT)->name} / 180)";
        $long1 = "(PI() * {Entity::F(self::_GEO_LONG)->name} / 180)";
        $a = "(
            POWER(SIN(($lat0 - $lat1) / 2), 2) +
            COS($lat0) *
            COS($lat1) *
            POWER(SIN(($long0 - $long1) / 2), 2)            
        )";
        $c = "(2 * ATAN2(POWER($a, .5), POWER(1 - $a, .5)))";
        $d = "6371000 * $c";
        return $d;
    }
)

Entity Relation

In almost any back-end project, some Entities are in relation with each other. For example, in a simple food delivery app, restaurants are handling orders, orders have items, items are being liked/ commented by users, users are ordering orders, restaurants are being liked/ commented by users, etc.
There is a unique and special Super called EntityRelation responsible for handling such relations.
But before we discuss this Super, we need to discuss different relations classes based on how we implement them.

A Little Formalism on Relation Classes

Assume $\mathcal{A}$ and $\mathcal{B}$ are two Entities, and $A$ and $B$ are sets of their instances, respectively. $R \subseteq A \times B$ is called a relation between $\mathcal{A}$ and $\mathcal{B}$. We define nine different classes of relations based on how we implement them. Any possible relation fits in one of these classes; actually, all of them fit in $\mathsf{NN}$. However, choosing the best class when defining the database structure is a matter of restriction and efficiency.
1. $\mathsf{O11O}$ (Optional one-to-one Optional) is the class of all relations with the following conditions. \begin{eqnarray*} & i. & \forall a \in A, |\{ b \in B : aRb \}| \leq 1 \\ & ii. & \forall b \in B, |\{ a \in A : aRb \}| \leq 1 \end{eqnarray*}
2. $\mathsf{O11R}$ (Optional one-to-one Required) is the class of all relations with the following conditions. \begin{eqnarray*} & i. & \forall a \in A, |\{ b \in B : aRb \}| \leq 1 \\ & ii. & \forall b \in B, |\{ a \in A : aRb \}| = 1 \end{eqnarray*}
3. $\mathsf{R11O}$ (Required one-to-one Optional) is the class of all relations with the following conditions. \begin{eqnarray*} & i. & \forall a \in A, |\{ b \in B : aRb \}| = 1 \\ & ii. & \forall b \in B, |\{ a \in A : aRb \}| \leq 1 \end{eqnarray*}
4. $\mathsf{R11R}$ (Required one-to-one Required) is the class of all relations with the following conditions. \begin{eqnarray*} & i. & \forall a \in A, |\{ b \in B : aRb \}| = 1 \\ & ii. & \forall b \in B, |\{ a \in A : aRb \}| = 1 \end{eqnarray*}
5. $\mathsf{ON1}$ (Optional many-to-one) is the class of all relations with the following condition. \begin{eqnarray*} \forall a \in A, |\{ b \in B : aRb \}| \leq 1 \end{eqnarray*}
6. $\mathsf{RN1}$ (Required many-to-one) is the class of all relations with the following condition. \begin{eqnarray*} \forall a \in A, |\{ b \in B : aRb \}| = 1 \end{eqnarray*}
7. $\mathsf{1NO}$ (one-to-many Optional) is the class of all relations with the following condition. \begin{eqnarray*} \forall b \in B, |\{ a \in A : aRb \}| \leq 1 \end{eqnarray*}
8. $\mathsf{1NR}$ (one-to-many Required) is the class of all relations with the following condition. \begin{eqnarray*} \forall b \in B, |\{ a \in A : aRb \}| = 1 \end{eqnarray*}
9. $\mathsf{NN}$ (many-to-many) is the class of all relations.

The Signature

The EntityRelation has the following signature.
EntityRelation{
    arguments {
        # Standard Arguments
              relatedEntity : Universal(                            )        ;
              relation      : Enum     (values   = self::REL_       )        ;
              invName       : Symbol   (nullable = true             ) = null ;
        # Constant Arguments
        const fromMany      : Boolean  (                            ) = false;
        const fromOne       : Boolean  (                            ) = false;
        const toMany        : Boolean  (                            ) = false;
        const toOne         : Boolean  (                            ) = false;
        const is11          : Boolean  (                            ) = false;
        const isN1          : Boolean  (                            ) = false;
        const is1N          : Boolean  (                            ) = false;
        const isNN          : Boolean  (                            ) = false;
        const optional      : Boolean  (                            ) = false;
        const nullable      : Boolean  (                            ) = false;
        const required      : Boolean  (                            ) = false;
        const invOptional   : Boolean  (                            ) = false;
        const invRequired   : Boolean  (                            ) = false;
        const hasJunction   : Boolean  (                            ) = false;
        # Definition Side Arguments
              definedOn     : Enum     (values   = self::DEFINED_ON_)        ;
        const definedHere   : Boolean  (                            ) = false;
        const definedThere  : Boolean  (                            ) = false;
        const columnHere    : Boolean  (                            ) = false;
        const columnThere   : Boolean  (                            ) = false;
    }
    ...
}
To create a relation $R$ between two Entities $\mathcal{L}$ and $\mathcal{R}$, one has to define a field that represents $R$ with a type generated from the EntityRelation Super. The field must be defined on $\mathcal{L}$ (called the Left Entity), and the relatedEntity must be set to $\mathcal{R}$ (called the Right Entity).
Relation Class
The relation argument determines the class of the relation and has one of the following values.
EntityRelation::REL_O11O
EntityRelation::REL_O11R
EntityRelation::REL_R11O
EntityRelation::REL_R11R
EntityRelation::REL_ON1
EntityRelation::REL_RN1
EntityRelation::REL_1NO
EntityRelation::REL_1NR
EntityRelation::REL_NN
Name & Inverse Name
One can use this field to get all the related rows of a row in the database. The invName argument is used to do the inverse job. We try to make it clear by an example.
Assume one defines a field called rel on the LeftEntity like this.
LeftEntity {
    fields {
        ...
        rel : EntityRelation(
            relatedEntity = @php(RightEntity::class),
            relation = EntityRelation::REL_NN,
            invName = 'invRel',
        )
        ...
    }
    ...
}
The Xua engine automatically generates an implicit field like this.
RightEntity {
    fields {
        ...
        invRel : EntityRelation(
            relatedEntity = @php(LeftEntity::class),
            relation = EntityRelation::REL_NN,
            invName = 'rel',
        )
        ...
    }
    ...
}
Now, one can access the related instances using these fields.
$l = new LeftEntity();
// $l->rel is the set of all instances of RightEntity $r s.t. $l is in relation with $r.
$r = new RightEntity();
// $r->invRel is the set of all instances of LeftEntity $l s.t. $l is in relation with $r.
Note. In the X-to-one cases, the result of retrieving a field is not a set but instead a value that can be an empty Entity in optional cases.
Note. The invName argument is optional, and if it is not provided, the Xua engine does not generate the implicit inverse field.
Constant Arguments
EntityRelation offers a set of constant arguments calculated based on the relation class, that help with recognizing a relation better. The names are pretty explanatory by themselves, but here we provide the way we calculate each.
$this->fromMany     = in_array($this->relation, [self::REL_NN, self::REL_ON1, self::REL_RN1]);
$this->fromOne      = !$this->fromMany;
$this->toMany       = in_array($this->relation, [self::REL_NN, self::REL_1NO, self::REL_1NR]);
$this->toOne        = !$this->toMany;
$this->is11         = ($this->fromOne and $this->toOne);
$this->isN1         = ($this->fromMany and $this->toOne);
$this->is1N         = ($this->fromOne and $this->toMany);
$this->isNN         = ($this->fromMany and $this->toMany);
$this->optional     = in_array($this->relation, [self::REL_O11O, self::REL_O11R, self::REL_ON1]);
$this->nullable     = $this->optional;
$this->required     = !$this->optional;
$this->invOptional  = in_array($this->relation, [self::REL_O11O, self::REL_R11O, self::REL_1NO]);
$this->invRequired  = !$this->invOptional;
$this->hasJunction  = $this->isNN;
Definition Side Arguments
There is a particular argument called definedOn which can either be here or there. This argument is not to be filled by the Xua programmer. If a relational field is defined explicitly on an Entity, the Xua engine sets this argument to here, and for the implicit inverse field, the value of this argument is there. There are also some constant fields in this regard; all of these arguments are used by the Xua core to decide how to store and process data.
$this->definedHere  = ($this->definedOn == self::DEFINED_ON_HERE);
$this->definedThere = ($this->definedOn == self::DEFINED_ON_THERE);
$this->columnHere   = (($this->is11 and $this->definedHere) or $this->isN1);
$this->columnThere  = (($this->is11 and $this->definedThere) or $this->is1N);

Entity Relation Example

For example, assume we have two Entities called User and City. Further, assume we want a field in the User entity called currentCity, and we want this field to refer to a row of the City table. We have to add the following field to the User entity.
User {
    fields {
        ...
        currentCity : EntityRelation(
            relatedEntity = @php(City::class),
            relation = EntityRelation::REL_RNI,
            invName = 'citizens',
        )
        ...
    }
    ...
}
Relation. The EntityRelation::REL_RNI stands for a many-to-one relation required on the left side, which means that no user can be in more than one city simultaneously but needs to be in a city, although one city can have many citizens at once.
Inverse Name. Here, we created a field called currentCity that shows us a relation between users and cities, and we can get related cities of a user by $user->currentCity, but how can we get related users of a city? The Xua engine generates an implicit field based on the invName. So $city->citizens gives us the list of all users that their currentCity is $city.

Field Class

Each field defined under a name is accessible using the static method Entity::F({fieldName}) of the entity class. This property is an instance of a class called EntityFieldSignature. This class has the following structure.
public string   $entity,
public string   $name,
public Super    $type,
public mixed    $default = null,
public function p(?array $param = null): array|EntityFieldSignature;

Field Class Example

Assume the Database Virtual Field Example we have provided above. Here we work a little around the field $restaurant->distance.
Notations Restaurant::fieldSignatures()[Restaurant::DISTANCE] and Entity::F(Restaurant::_DISTANCE) both refer to the same value, an instance of class EntityFieldSignature describing this field. So we know the following expressions are true.
Entity::F(Restaurant::_DISTANCE)->entity  == Restaurant::class;
Entity::F(Restaurant::_DISTANCE)->name    == 'distance';
Entity::F(Restaurant::_DISTANCE)->type    == DatabaseVirtualField (...);
Entity::F(Restaurant::_DISTANCE)->default == null;
// The parameters of a field is null by default.
Entity::F(Restaurant::_DISTANCE)->p()     == null;
// We can modify the parameters of a field by calling the method `p` on its signature.
Entity::F(Restaurant::_DISTANCE)->p(['here' => (object)['lat' => 42, 'long' => 59]]); // https://en.wikipedia.org/wiki/Khwarazm
// Now it is set.
Entity::F(Restaurant::_DISTANCE)->p()     == ['here' => (object)['lat' => 42, 'long' => 59]];

Conditional Field Class

The ConditionField class is similar to the regular field class but has some features used in defining conditions and orders, which we discuss later. The Condition Field of each field is accessible as the static method Entity::C({fieldName}) of the entity class. This class has the following structure.
public function __construct(public EntityFieldSignature $signature);
public function rel(ConditionField $conditionField): static;
public function name() : string;
public function joins(): array;
So the Entity::C({fieldName}) is actually new ConditionField(Entity::F({fieldName})), an instance of ConditionField based on the field signature.
The critical feature of this class is the rel method, which makes it possible to access fields on the related tables. We cover this in the Condition and Order sections.
The methods name and joins are not usually helpful for the Xua programmer and are used in the Xua core. So we do not cover them here.

Condition

Condition is a Xua built-in class that we use to create WHERE expressions with.
Theoretically speaking, a condition node is a deciding machine that inputs a row of a specific table and returns a boolean that indicates whether the given row is accepted in the condition or not.
Each instance of Condition is a node in a semi-binary tree. There are two ways two create an instance of this class. One is to create a new node (a leaf), and the other is to operate on existing nodes.

Leaf Condition

There are three common types of leaf conditions: relational leaf, true leaf, and false leaf. However, one can create a custom leaf as a raw leaf.
Relational Leaf
The method for creating a relational leaf is the following.
Condition::leaf(ConditionField $field, string $relation, mixed $value = null);
This method will create a condition asserting that the field $filedName must be in $relation relation with the value $value.
Field
As described above, for each entity, conditional fields are available as instances of ConditionField using the static methods of the form Entity::C({fieldName}).
Relation
XUA also provides relation constants as class constants of the Condition class. These constants are listed below.
Name SQL equivalent Description
Condition::GRATER > Greater than
Condition::NGRATER <= Negation of GRATER
Condition::GRATEREQ >= Greater than or equal
Condition::NGRATEREQ < Negation of GRATEREQ
Condition::LESS < Less than
Condition::NLESS >= Negation of LESS
Condition::LESSEQ <= Less than or equal
Condition::NLESSEQ > Negation of LESSEQ
Condition::EQ = Equal
Condition::NEQ != Negation of EQ
Condition::NULLSAFEEQ <=> NULL-safe equal
Condition::NNULLSAFEEQ !(... <=> ...) Negation of NNULLSAFEEQ
Condition::BETWEEN BETWEEN ... AND ... Whether a value is within a range of values (This relation requires the argument $value to be an array consisting of two values)
Condition::NBETWEEN NOT BETWEEN ... AND ... Negation of BETWEEN
Condition::IN IN Whether a value is within a set of values (This relation requires the argument $value to be an array of values)
Condition::NIN NOT IN Negation of IN
Condition::IS IS Test a value against a boolean
Condition::NIS IS NOT Negation of IS
Condition::ISNULL IS NULL NULL value test (This relation does not depend on value of argument $value)
Condition::NISNULL IS NOT NULL Negation of ISNULL (This relation does not depend on value of argument $value)
Condition::LIKE LIKE Simple pattern matching
Condition::NOT_LIKE NOT LIKE Negation of LIKE
Condition::REGEXP REGEXP Simple regular expression pattern matching
Condition::NOT_REGEXP NOT REGEXP Negation of REGEXP
Value
The value argument must usually fit in the field type. However, in some cases (some relations), one value does not suffice (e. g. Condition::BETWEEN), so we need to provide two values of the field type as an array.
To create a condition node that presents a condition on one of the related entities, one can use the rel method on condition field instances.
Example
For example, a condition node that asserts that a person is born in the '90s would look like the following.
Condition::leaf(
    Entity::C(User::_BIRTH_DATE),
    Condition::BETWEEN,
    [
        DateTimeInstance::fromGregorianYmd('1990-1-1'),
        DateTimeInstance::fromGregorianYmd('2000-1-1')
    ]
)
As an other example, assume we want to have a condition that refers to all posts written by people living in Palo Alto. We may use the following node.
Condition::leaf(
    Entity::C(Post::AUTHOR)
        ->rel(Entity::C(User::_LIVING_IN))
        ->rel(Entity::C(AdministrativeDivision::_TITLE)),
    Condition::EQ,
    'Palo Alto'
)
True Leaf & False Leaf
The special leaf methods Condition::trueLeaf() and Condition::falseLeaf() are always true and false respectively.
Raw Leaf
The raw leaf method is described as follows.
Condition::rawLeaf(string $template, array $parameters = [], array $joins = [])
This method is used to inject pure and raw SQL script to the WHERE expression in case other leaf methods do not satisfy the programmer's needs. The use of this method is highly discouraged as the other methods are powerful enough to satisfy almost all of the programmer's needs. Still, a somehow funny usage of this method would be the following.
Condition::rawLeaf("RAND() > ?", [0.5])
We will discuss parameter binding used in the above code in more detail later.

Operations on Conditions

In addition to the above methods for creating new leaf nodes, Xua provides some methods to create new nodes using existing nodes.
Logical Operators
four logical operators are used to create a new node using existing nodes. These operators are binary-operators AND, OR, XOR, and unary-operator NOT.
Classic Operators
The primitive way to create a new node is to provide operands to an operator and receive a new node as the return value. The four methods for this are the followings.
public static function _and_(Condition $leftCondition, Condition $rightCondition): Condition;
public static function _or_(Condition $leftCondition, Condition $rightCondition): Condition;
public static function _xor_(Condition $leftCondition, Condition $rightCondition): Condition;
public static function _not_(Condition $condition): Condition;
High-Level Operators
Although the described methods can theoretically create any condition, Xua provides some methods to improve code readability.
C Operators
The first group is called the C (Condition) group. These methods are used on a node to connect it to another node.
public function andC(Condition $condition): Condition;    
public function orC(Condition $condition): Condition
public function xorC(Condition $condition): Condition;
public function not(): Condition;
For example, take a look at the following code.
$l = Condition::trueLeaf();
// $l is now rendered as 'TRUE'
$l->andC(Condition::falseLeaf());
// $l is now rendered as '(TRUE) AND (FALSE)'
$l->not();
// $l is now rendered as 'NOT ((TRUE) AND (FALSE))'
Common Operators
These methods are used on a node to connect it to a relational node, but the creation of the second node is embedded.
public function and(ConditionField $field, string $relation, mixed $value = null): Condition
{
    return $this->andC(Condition::leaf($field, $relation, $value));
}
public function or(ConditionField $field, string $relation, mixed $value = null): Condition
{
    return $this->orC(Condition::leaf($field, $relation, $value));
}
public function xor(ConditionField $field, string $relation, mixed $value = null): Condition
{
    return $this->xorC(Condition::leaf($field, $relation, $value));
}
R Operators
This group is called the R (Raw) group. These methods are used on a node to connect it to a raw node, but the creation of the second node is embedded.
public function andR(string $template, array $parameters = [], array $joins = []): Condition
{
    return $this->andC(Condition::rawLeaf($template, $parameters, $joins));
}
public function orR(string $template, array $parameters = [], array $joins = []): Condition
{
    return $this->orC(Condition::rawLeaf($template, $parameters, $joins));
}
public function xorR(string $template, array $parameters = [], array $joins = []): Condition
{
    return $this->xorC(Condition::rawLeaf($template, $parameters, $joins));
}

Order

Order is a Xua built-in class that is usually used to create ORDER BY expressions.
To create an instance of this class, one needs to start with an empty instance and append order expressions. Each new order appended has a lesser priority than the last one. The bootstrap instance is created using the following method.
Order::noOrder(): Order;
To append a raw order expression in SQL syntax, one may use the following method, but it is highly discouraged.
public function addRaw(string $order): Order;
To append an order based on an entity field, one may use the following method, which is preferred.
public function add(ConditionField $field, string $direction): Order
{
    return $this->addRaw($field->name() . ' ' . $direction);
}
Note that the direction can be one of the values Order::ASC and Order::DESC.
There are some other come in handy methods to use in order to avoid using the addRaw method, such as the following.
public function addRandom(): Order
{
    return $this->addRaw('RAND()');
}

Pager

Pager is a Xua built-in class that is usually used to generate LIMIT ... OFFSET ... expressions.
Each class instance contains these arguments (limit and offset) as properties, but it is a good practice not to modify them manually. The class constructor takes two arguments, $pageSize and $pageIndex, and calculates the limit and offset values according to them. It is possible to modify these arguments as well. There is also one specific instance accessible usingPager::unlimited(), which is used to fetch all rows. The following properties and methods are present in the pager class.
Properties Description
private int $pageSize; Page Size
private int $pageNumber; Page Number
Methods Description
<em></em>construct(int $pageSize, int $pageNumber); Creates a new instance with the given data.
next(); Goes to the next page.
previous(); Goes to the previous page.
getPageSize(); Returns page size.
setPageSize(int $pageSize); Sets page size.
getPageNumber(); Returns page number.
setPageNumber(int $pageNumber); Sets page number.
static pages(Condition $condition, int $pageSize); Returns the number of pages if we store rows of $entityName under $condition in pages of size $pageSize.
Note. The pages start from one.

Deploy & Alters

When a new Entity is created, or modified, these changes should be synced with the MySQL server. There is a particular service called EntityAlterService, which is responsible for doing this. The static method alters(): string on this class adds newly created entities as tables to the database by itself and returns ALTER queries for modified entities. This method does not run the alters by itself, instead, it prints out the alters; which are possible to run by the programmer or another person in charge.
The convention is to use this method in the deploy procedure, check for the alters, and generate a warning if the database structure is not synced with the program. It is also a convention to give developers the ability to complete the deploy process with the undone alters. This process is called force deploy, and the alters which are possible to ignore while deploying are called force-friendly alters.

Usage

It is possible to use a defined entity in both server project (PHP language) and front-end native codes via the Marshal Library, but not in the Xua source codes. The usage in the Marshal Library is controlled via the visibility of entity methods and the modification of URPI, and it is not that different from the PHP usage.
In this section, we try to cover all methods, properties, and constants available on an Entity class.

Properties & Constants

Xua generates a class property and a class constant for each field defined in an entity. The property is defined on each instance and refers to the corresponding value in the database, while the constant (named <em>{FIELD</em>NAME<em>IN</em>SCREAMING<em>SNAKE</em>CASE}) contains the field name. For example for field birthDate on User, Xua generate $user->birthDate and User::<em>BIRTH</em>DATE = 'User.birthDate'. This constant can be used to get Field and Conditional Field instances using Entity::F(User::<em>BIRTH</em>DATE) and Entity::C(User::<em>BIRTH</em>DATE) respectively.

Helpers

@TODO

Execute

@TODO

Indexes

@TODO

Fields

@TODO

Table

@TODO

VARQUE Actions

In order to discuss other entity methods, we need to discuss the VARQUE actions first.
There are different actions that one can take on a database. We divide these functionalities into three categories: Select Data Actions, Create/Modify Data Actions, and Delete Data Actions. We may also divide the functions based on whether they act on a single row or a group of rows, which takes us to two categories Singular Actions and Conditional Actions. This gives us six types of actions, which we name each one as follows.
Retrieve Create/Modify Delete
Singular View Adjust Remove
Conditional Query Update Eliminate
These actions are called the VARQUE (View, Adjust, Remove, Query, Update, Eliminate) actions.

View

Two methods are used to retrieve a single row of a table. The first one has the following signature.
static function getOne(
    ?Condition $condition = null,
    ?Order $order = null,
    string $caller = Visibility::CALLER_PHP
): static;
This function takes an instance of the Condition class and an instance of the Order class (both are described before) and returns the first row (ordered by $order) that matches the $condition criteria. If no such row is found, it returns an empty instance of the entity. To check if an instance of an entity class is empty, one can check if the id property is null or not ($entity->id === null or not).
The second one is the class constructor.
function __construct(?int $id = null);
This function is just an alias for the following call, designed for simplicity.
EntityName::getOne(
    Condition::leaf(
        Entity::C(EntityName::_ID),
        Condition::EQ,
        $id
    )
);

Query

@TODO getMany and count

Adjust

@TODO store

Update

@TODO storeMany and EntityBuffer

Remove

@TODO delete

Eliminate

@TODO deleteMany