Cycle ORM can be installed into any PHP application using composer dependency manager.


  • PHP 7.2+
  • PDO drivers for desired databases


Cycle ORM is available as a composer package and can be installed using the following command in the root of your project:

$ composer require cycle/orm

In order to enable support for annotated entities you have to install an additional package:

$ composer require cycle/annotated

This command will also download Cycle ORM dependencies such as spiral/database, doctrine/collections and zendframework/zend-hydrator.

In order to access Cycle ORM classes make sure to include vendor/autoload.php in your file.

<?php declare(strict_types=1);
include 'vendor/autoload.php';

Connect Database

In order to connect Cycle to the proper database instance, you must configure the instance of Spiral\Database\DatabaseManager. The details of this configuration process described in a following section.

Instantiate ORM

An ORM service can be instantiated using the Cycle\ORM\ORM class, which takes only one dependency on Cycle\ORM\Factory:

use Cycle\ORM;

$orm = new ORM\ORM(new ORM\Factory($dbal));

Schema Generation (Schema Update)

In order to operate Cycle ORM a schema definition is required. The schema will contain a list of available entities, their relations, and association with a specific database.

The schema can be described manually by instantiating Cycle\ORM\Schema object:

use Cycle\ORM\Schema;
use Cycle\ORM\Relation;
use Cycle\ORM\Mapper\Mapper;

$schema = new Schema([
    'user' => [
        Schema::ENTITY      => User::class,
        Schema::MAPPER      => Mapper::class,
        Schema::DATABASE    => 'default',
        Schema::TABLE       => 'user',
        Schema::PRIMARY_KEY => 'id',
        Schema::COLUMNS     => [
            'id'      => 'id',
            'email'   => 'email',
            'balance' => 'balance'
        Schema::TYPECAST    => [
            'id'      => 'int',
            'balance' => 'float'
        Schema::SCHEMA      => [],
        Schema::RELATIONS   => [
            'address' => [
                 Relation::TYPE   => Relation::HAS_ONE,
                 Relation::TARGET => 'address',
                 Relation::SCHEMA => [
                     Relation::CASCADE   => true,
                     Relation::INNER_KEY => 'id',
                     Relation::OUTER_KEY => 'user_id',
    'address' => [
        Schema::ENTITY      => Address::class,
        Schema::MAPPER      => Mapper::class,
        Schema::DATABASE    => 'default',
        Schema::TABLE       => 'address',
        Schema::PRIMARY_KEY => 'id',
        Schema::COLUMNS     => [
            'id'      => 'id',
            'user_id' => 'user_id',
            'city'    => 'city'
        Schema::TYPECAST    => [
            'id'      => 'int'
        Schema::SCHEMA      => [],
        Schema::RELATIONS   => []

$orm = $orm->withSchema($schema);

However, in order to simplify the integration, it is recommended to use a schema compiler provided by cycle/schema-builder extension. Such compiler is able to automatically index all available entities, perform database introspection and reflection.

To compile the schema using annotated entities and automatically configure the database use the following pipeline:

use Cycle\Schema;
use Cycle\Annotated;
use Spiral\Tokenizer;

// Class locator
$cl = (new Tokenizer\Tokenizer(new Tokenizer\Config\TokenizerConfig([
    'directories' => ['src/'],

$schema = (new Schema\Compiler())->compile(new Schema\Registry($dbal), [
    new Annotated\Embeddings($cl),            // register embeddable entities
    new Annotated\Entities($cl),              // register annotated entities
    new Schema\Generator\ResetTables(),       // re-declared table schemas (remove columns)
    new Annotated\MergeColumns(),             // copy column declarations from all related classes (@Table annotation)
    new Schema\Generator\GenerateRelations(), // generate entity relations
    new Schema\Generator\ValidateEntities(),  // make sure all entity schemas are correct
    new Schema\Generator\RenderTables(),      // declare table schemas
    new Schema\Generator\RenderRelations(),   // declare relation keys and indexes
    new Annotated\MergeIndexes(),             // copy index declarations from all related classes (@Table annotation)
    new Schema\Generator\SyncTables(),        // sync table changes to database
    new Schema\Generator\GenerateTypecast(),  // typecast non string columns

$orm = $orm->withSchema(new \Cycle\ORM\Schema($schema));

The result of the schema builder is a compiled schema. The given schema can be cached in order to avoid expensive calculations on each request.

In the following section the terming update schema will be referenced to this process.

Remove element new Schema\Generator\SyncTables() to disable database reflection. In a later section, we will describe how to automatically render database migrations instead of direct synchronization.

Edit this page