Zend Expressive and Cycle ORM.
Tags: php, zendexressive, orm, cycle
Published: 2019-07-03 19:13:32

  Hello, community. I decided to write a short article is dedicated to [Zend Expressive(ZE)](https://docs.zendframework.com/zend-expressive/) & [Cycle ORM(CycleORM)](https://github.com/cycle/orm). Let's go ahead! 
  For setting up ZE there can be used [the skeleton application and installer](https://github.com/zendframework/zend-expressive-skeleton). 
  It's an easy way of starting working with ZE. After that, to add CycleORM dependancies: 
```
composer require cycle/orm
composer require cycle/annotated
composer require cycle/schema-builder
```
  For the next step, should add a folder (call like 'cycle-factories' or another name as willing):
```
project    
│
└───cycle-factories
│      └───CycleFactory.php
       └───TransactionFactory.php

```
  Should change composer-autoload, can look like:
```json
   "autoload": {
        "psr-4": {
            "App\\": "src/App/src/",
            "Cycle\\": "cycle-factories/"
        }
    },
```
  CycleFactory.php
```php
<?php declare(strict_types=1);

namespace Cycle;

use Cycle\Annotated\{Embeddings, Entities};
use Cycle\ORM\{Factory, ORM, ORMInterface, Schema as OrmSchema};
use Cycle\Schema\{Compiler, Registry};
use Cycle\Schema\Generator\{GenerateRelations,
    GenerateTypecast,
    RenderRelations,
    RenderTables,
    ResetTables,
    SyncTables,
    ValidateEntities};
use Psr\Container\ContainerInterface;
use Spiral\Database\{DatabaseManager};
use Spiral\Database\Config\{DatabaseConfig};
use Spiral\Database\Exception\{ConfigException};
use Spiral\Tokenizer\ClassLocator;
use Symfony\Component\Finder\Finder;

class CycleFactory
{
    /**
     * @param ContainerInterface $container
     * @return ORMInterface
     */
    public function __invoke(ContainerInterface $container): ORMInterface
    {
        $config = $container->has('config')
            ? $container->get('config')
            : [];

        if (!isset($config['cycle'])) {
            throw new ConfigException('Expected config databases');
        }
        $config = $config['cycle'];
        $entities = $config['entities'];
        $finder = (new Finder())->files()->in($entities);
        $cl = new ClassLocator($finder);
        $dbal = new DatabaseManager(new DatabaseConfig($config));
        $schema = (new Compiler())->compile(new Registry($dbal), [
            new Embeddings($cl),     // register embeddable entities
            new Entities($cl),       // register annotated entities
            new ResetTables(),       // re-declared table schemas (remove columns)
            new GenerateRelations(), // generate entity relations
            new ValidateEntities(),  // make sure all entity schemas are correct
            new RenderTables(),      // declare table schemas
            new RenderRelations(),   // declare relation keys and indexes
            new SyncTables(),        // sync table changes to database
            new GenerateTypecast(),  // typecast non string columns
        ]);
        $orm = new ORM(new Factory($dbal));
        $orm = $orm->withSchema(new OrmSchema($schema));
        return $orm;
    }
}
```
  TransactionFactory.php
```php
<?php declare(strict_types=1);

namespace Cycle;

use Cycle\ORM\ORMInterface;
use Cycle\ORM\Transaction;
use Cycle\ORM\TransactionInterface;
use Psr\Container\ContainerInterface;

class TransactionFactory
{
    /**
     * @param ContainerInterface $container
     * @return TransactionInterface
     */
    public function __invoke(ContainerInterface $container): TransactionInterface
    {
        return new Transaction($container->get(ORMInterface::class));
    }
}
```
  For the next step, should add a config file:
```
project    
│
└───config
│   │
│   └───autoload
│       └───cycle.global.php(cycle.local.php)
│       │   ...

```
  cycle.global.php can look like (For another configuration to follow [the documentation link](https://github.com/cycle/docs/blob/master/basic/connect.md)):
```php
<?php declare(strict_types=1);

use Spiral\Database;

return [
    'cycle' => [
        'default' => 'default',
        'databases' => [
            'default' => ['connection' => 'sqlite']
        ],
        'connections' => [
            'sqlite' => [
                'driver' => Database\Driver\SQLite\SQLiteDriver::class,
                'connection' => 'sqlite:database.db',
                'username' => '',
                'password' => '',
            ]
        ],
        'entities' => [//array of Entities 
            'src/App/src/Entities'//it depends on a structure of the project
        ]
    ]
];
```
  For the next step, should add global dependencies:
```
project    
│
└───config
│   │
│   └───autoload
│       └───dependencies.global.php(dependencies.local.php)
│       │   ...

```
  dependencies.global.php can look like:
```php
<?php declare(strict_types=1);

return [

      ...

        'factories'  => [
            \Cycle\ORM\ORMInterface::class => \Cycle\CycleFactory::class,
            \Cycle\ORM\TransactionInterface::class => \Cycle\TransactionFactory::class,
        ],
    ],
];

```
  For testing Cycle ORM to look at an attached screenshot [use example](https://a.imge.to/2019/07/04/30qRr.png).