Siesta
Stored procedure based object relational mapper for php7

Content


Overview


Siesta is an object relational mapper for php7 build for performant database access implementing the active record pattern. Furthermore it allows to define own plugins to generate custom coding into entity or service classes or even generate additional classes like DTO. The database access is realized with stored procedures for all standard operations. Custom stored procedure can be defined in xml format. Currently only drivers for for MySQL are available.

Important features:

Code Generation
Instead of writing a large generic engine with tons of code, the needed code for persistency operations is generated from descriptions. Therefore the needed persistency footprint is very small, hence fast.

Stored Procedures insted of ad-hoc SQL
Siesta relies to 100% on Stored Procedures. The generator creates all needed stored procedures directly in the database. In contrast to classic ad hoc sql the stored procedures are precompiled in the database which increases performance. Furthermore custom stored procedures can be defined.

Extensibility
Code generation approaches tend to limit programmers ability to change behaviour. Therefore an import design principle is to allow for extensibilty at every given point. Own generator plugins can be defined or existing ones replaced or overwritten.

In Memory replication
Siesta for MySQL allows to replicate tables with a memory engine. That means the table exist twice once with the defined engine and one with the memory engine. All modifying operations are executed on both tables. Read operations are only performed on the memory table.

Delimiting Tables / Record History
Sometimes it is important to track changes to objects. Therefore Siesta allows to generate a second history table. Every time the a record is changed, the changes will be stored to the history table with a valid from and valid until entry.

code coverage report

Installation


Installation with composer

composer require gm314/siesta

Create configuration file with

vendor/bin/siesta init

SSH Clone URL : git@github.com:gperler/siesta.git
Github repository https://github.com/gperler/siesta

Hello World


(1) After having installed Siesta run vendor/bin/siesta init on the command line. It will ask you for database connection details and generate an initial configuration file.

(2) Copy the following xml into a file called hello.entity.xml. And place it somewhere in your project directory. The suffix .entity.xml is important, because Siesta will by default look for all files that end with .entity.xml. You can change this in the config file.

    <entityList>

        <entity name="Customer" namespace="Siesta\HelloWorld" table="Customer">
            <attribute name="id" type="int" dbType="INT" primaryKey="true" required="true" autoValue="autoincrement"/>
            <attribute name="firstName" type="string" dbType="VARCHAR(100)"/>
            <attribute name="lastName" type="string" dbType="VARCHAR(100)"/>

            <collection name="addressList" foreignTable="Address" foreignReferenceName="customer"/>
        </entity>

        <entity name="Address" namespace="Siesta\HelloWorld" table="Address">
            <attribute name="id" type="int" dbType="INT" primaryKey="true" required="true" autoValue="autoincrement"/>
            <attribute name="name" type="string" dbType="VARCHAR(100)"/>
            <attribute name="customerId" dbName="fk_customer" type="int" dbType="INT"/>

            <reference name="customer" foreignTable="Customer" onDelete="cascade" onUpdate="cascade">
                <referenceMapping localAttribute="customerId" foreignAttribute="id"/>
            </reference>
        </entity>

    </entityList>

(3) Run vendor/bin/siesta gen on the command line. This will generate 4 files in the folder src/Siesta/HelloWorld. See configuration below to change this.

  • Customer.php this class represents the customer table with functionality like save delete
  • CustomerService.php this class contains management like find by primary keys
  • Address.php same like Customer for Address entity
  • AddressService.php same like CustomerService for Address entity
Below you can find an example usage of the classes.

<?php

namespace test;

use Siesta\Config\Config;
use Siesta\HelloWorld\Address;
use Siesta\HelloWorld\Customer;

require_once 'vendor/autoload.php';

// will load database configuration
Config::getInstance();

// create a new Address
$address = new Address();
$address->setName("London Residence");

// create a new Customer
$customer = new Customer();
$customer->setLastName("Woon");
$customer->setFirstName("Jamie");
$customer->addToAddressList($address);

// true enables the cascading save. The customer including the address will be saved.
$customer->save(true);

Console Commands & Configuration


Init and the config file

First you should use vendor/bin/siesta init to create a config file. The command will aks for your database connection data and test the connection. It will create a file called siesta.config.json. If no other config file is specified Siesta will always search for this file.

The config file generated consist of 3 parts. Connection, Generator and Reverse.

    {
        "connection": [
            { ... }
        ],
        "generator": {
           ...
        },
        "reverse": {
          ...
        }
    }
                            

Connection

Most values are self explanatory. Currently there is only a MySQL driver. The driver value points to the driver class implementing the Siesta\Database\Driver interface. In the postConnectStatementList you can place several statements that are executed after connection. You can even define several connections. The database access methods provide an optional parameter called $connectionName If supplied you can tell Siesta to use the specific connection. If the parameter is not set, Siesta will use the default configuration.

    {
            "name": "default",
            "driver": "Siesta\\Driver\\MySQL\\MySQLDriver",
            "host": "127.0.0.1",
            "port": 3306,
            "database": "siesta2",
            "user": "root",
            "password": "",
            "charSet": "utf8",
            "isDefault": null,
            "postConnectStatementList": []
    }

Generate and Generate Config

The command vendor/bin/siesta gen --configFile myConfig.json will scan the current working directory for entity xml files and generate the PHP classes and perform database migrations. The parameter --configFile is optional. If not supplied, Siesta will search for a file called siesta.config.json.

The generator part describes how the generator works. dropUnusedTables tells siesta if not used tables should be deleted or not.

The entityFileSuffix tells Siesta for which entity files it should look. By default it will scan your entire project directory and use all files that match the suffix.

The migrationMethod direct will update the database when running the command. You can also specify the value sql which will put alter statements into a file in the migrationTargetPath directory.

If you do not specify table name or dbName for columns the configures strategies tableNamingStrategy and columnNamingStrategy will be used to determine the names. A strategy is simply a class that implements the Siesta\NamingStrategy\NamingStrategy interface. You can implement your own strategy. Just place the class name in the configuration file and make sure your strategy is autoloaded. Available strategies are

  • Siesta\NamingStrategy\NoTransformStrategy
  • Siesta\NamingStrategy\ToCamelCaseStrategy
  • Siesta\NamingStrategy\ToClassCamelCaseStrategy (will uppercase the first character)
  • TSiesta\NamingStrategy\ToUnderScoreStrategy

The baseDir will tell Siesta where to put generated classes. By default paths are deriverd psr-0 compliant from the provivide namespace. Example. If the baseDir is "src" and the namespace is Siesta\HelloWord the class will be stored in src/Siesta/HelloWorld directory. When specifying a targetPath in the entity xml, the targetDirector will be baseDir/targetPath.

You can supply a specific connectionName for the generator. If none is supplied the default connection will be used for generating/migrating

The genericGeneratorConfiguration allows you to totally change the way that Siesta is generating entities and Service class. If you want to add your own code generator plugins or remove mehtods that you don't like or just enhance them, you can copy the default configuration, adapt the generators and have it your style. See the Generator section for more details.

    {
        "dropUnusedTables": true,
        "entityFileSuffix": ".entity.xml",
        "migrationMethod": "direct",
        "migrationTargetPath": "migration",
        "tableNamingStrategy": "Siesta\\NamingStrategy\\ToUnderScoreStrategy",
        "columnNamingStrategy": "Siesta\\NamingStrategy\\ToUnderScoreStrategy",
        "baseDir": "src",
        "connectionName": null,
        "genericGeneratorConfiguration": null
    }

Reverse engineer Command & Configuration

The console command vendor/bin/siesta gen --configFile myConfig.json will reverse engineer an existing database schema and create XML files. The --configFile parameter is optional.

The third reverse section in the config file describes how an existing schema is reverse engineered. The targetPath specifies where the xml should be stored. You can either place all information in one file (singleFile true) or create an XML file for every table. Therefore Siesta either uses the targetFile option or the entityFileSuffix.

classNamingStrategy and attributeNamingStrategy determine how Classes and attributes should be called based on the name of the table and the column. Available strategies are.

  • Siesta\NamingStrategy\NoTransformStrategy
  • Siesta\NamingStrategy\ToCamelCaseStrategy
  • Siesta\NamingStrategy\ToClassCamelCaseStrategy (will uppercase the first character)
  • TSiesta\NamingStrategy\ToUnderScoreStrategy
You can also create your own strategy by creating a class that implements the Siesta\NamingStrategy\NamingStrategy interface.

defaultNamespace allows you to specifiy which namespace should be used in the entity xml files. The connectionName allows to use a specific connection defined in the connection section.

    {
        "targetPath": "\/reverse",
        "singleFile": true,
        "targetFile": "Reverse.xml",
        "entityFileSuffix": ".entity.xml",
        "classNamingStrategy": "Siesta\\NamingStrategy\\ToClassCamelCaseStrategy",
        "attributeNamingStrategy": "Siesta\\NamingStrategy\\ToCamelCaseStrategy",
        "defaultNamespace": null,
        "connectionName": null
    }