loading...

Zend Expressive and Cycle ORM.

sergey_telpuk profile image Sergey Telpuk ・2 min read

Hello, community. I decided to write a short article is dedicated to Zend Expressive(ZE) & Cycle ORM(CycleORM). Let's go ahead!
For setting up ZE there can be used the skeleton application and installer.
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:

   "autoload": {
        "psr-4": {
            "App\\": "src/App/src/",
            "Cycle\\": "cycle-factories/"
        }
    },

CycleFactory.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 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):

<?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 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.

Discussion

pic
Editor guide