PHP DataMapper, ORM

Overview

Cycle ORM

Latest Stable Version Build Status Scrutinizer Code Quality Codecov

Cycle ORM

Cycle is PHP DataMapper, ORM and Data Modelling engine designed to safely work in classic and daemonized PHP applications (like RoadRunner). The ORM provides flexible configuration options to model datasets, powerful query builder and supports dynamic mapping schema. The engine can work with plain PHP objects, support annotation declarations, and proxies via extensions.

Website and Documentation | Comparison with Eloquent and Doctrine

Features:

  • clean and fast Data Mapper
  • ORM with has-one, has-many, many-through-many and polymorphic relations
  • Plain Old PHP objects, ActiveRecord, Custom objects or same entity type for multiple repositories
  • eager and lazy loading, query builder with multiple fetch strategies
  • embedded entities, lazy/eager loaded embedded partials
  • runtime configuration with/without code-generation
  • column-to-field mapping, single table inheritance, value objects support
  • hackable: persist strategies, mappers, relations, transactions
  • works with directed graphs and cyclic graphs using command chains
  • designed to work in long-running applications: immutable service core, disposable UoW
  • supports MySQL, MariaDB, PostgresSQL, SQLServer, SQLite
  • schema scaffolding, introspection, and migrations
  • supports global query constrains, UUIDs as PK, soft deletes, auto timestamps
  • custom column types, FKs to non-primary columns
  • use with or without annotations, proxy classes, and auto-migrations
  • compatible with Doctrine Collections, Doctrine Annotations, and Zend Hydrator

Extensions:

Component Current Status
cycle/schema-builder Latest Stable Version Build Status Scrutinizer Code Quality Codecov
cycle/annotated Latest Stable Version Build Status Scrutinizer Code Quality Codecov
cycle/proxy-factory Latest Stable Version Build Status Scrutinizer Code Quality Codecov
cycle/migrations Latest Stable Version Build Status Scrutinizer Code Quality Codecov

Example:

// load all active users and pre-load their paid orders sorted from newest to olders
// the pre-load will be complete using LEFT JOIN
$users = $orm->getRepository(User::class)
    ->select()
    ->where('active', true)
    ->load('orders', [
        'method' => Select::SINGLE_QUERY,
        'load'   => function($q) {
            $q->where('paid', true)->orderBy('timeCreated', 'DESC');
        }
    ])
    ->fetchAll();

$t = new Transaction($orm);

foreach($users as $user) {
    $t->persist($user);
}

$t->run();

License:

The MIT License (MIT). Please see LICENSE for more information. Maintained by Spiral Scout.

Comments
  • cycle\ORM\Exception\TransactionException Transaction can't be finished. Some relations can't be resolved: Update `product` - tax_rate (Cycle\ORM\Relation\BelongsTo)🐛

    cycle\ORM\Exception\TransactionException Transaction can't be finished. Some relations can't be resolved: Update `product` - tax_rate (Cycle\ORM\Relation\BelongsTo)🐛

    No duplicates 🥲.

    • [X] I have searched for a similar issue in our bug tracker and didn't find any solutions.

    What happened?

    Ubuntu 22.04 LTS Testing and Wampserver 3.2.9 Testing Above error common to both Windows and Ubuntu Apache2 using fork rossaddison/yii-invoice. Event: A new product, not used in any quote, or invoice, when tax_rate_id BelongsTo dropdown edited and saved. Also if the product's family group BelongsTo relation changes, and is saved, same error occurs.

    This error occurs when the record is edited, not created.

    This error did not occur when I was using annotations instead of the current Atributes. This issue is similar to issue #329

    Here is the entity that is being used:

    <?php
    
    declare(strict_types=1);
    
    namespace App\Invoice\Entity;
    
    use Cycle\Annotated\Annotation\Column;
    use Cycle\Annotated\Annotation\Entity;
    use App\Invoice\Entity\Family;
    use App\Invoice\Entity\TaxRate;
    use App\Invoice\Entity\Unit;
    use Cycle\Annotated\Annotation\Relation\BelongsTo;
    
    #[Entity(repository: \App\Invoice\Product\ProductRepository::class)]
    class Product
    {
        #[Column(type: 'primary')]
        private ?int $id = null;
            
        #[Column(type: 'text', nullable: true)]
        private ?string $product_sku = '';
        
        #[Column(type: 'text', nullable: true)]
        private ?string $product_name = '';
        
        #[Column(type: 'longText', nullable: false)]
        private ?string $product_description = '';
            
        #[Column(type: 'decimal(20,2)', nullable: true)]
        private ?float $product_price = null;
        
        #[Column(type: 'decimal(20,2)', nullable: true)]
        private ?float $purchase_price = null;
        
        #[Column(type: 'text', nullable: true)]
        private ?string $provider_name = '';
        
        #[BelongsTo(target:Family::class, nullable: false, fkAction: "NO ACTION")]
        private ?Family $family = null;        
        #[Column(type: 'integer(11)', nullable: true)]
        private ?int $family_id = null;
        
        // A product has to have a tax rate before it can be created even if it is a zero tax rate    
        #[BelongsTo(target:TaxRate::class, nullable: false, fkAction: "NO ACTION")]
        private ?TaxRate $tax_rate = null;    
        #[Column(type: 'integer(11)', nullable: false)]
        private ?int $tax_rate_id = null;
            
        #[BelongsTo(target:Unit::class, nullable: false, fkAction: "NO ACTION")]
        private ?Unit $unit = null;    
        #[Column(type: 'integer(11)', nullable: true)]
        private ?int $unit_id = null;
        
        #[Column(type: 'integer(11)', nullable: true)]
        private ?int $product_tariff = null;
        
        public function __construct(
            string $product_sku = '',
            string $product_name = '',
            string $product_description = '',
            float $product_price = null,
            float $purchase_price = null,
            string $provider_name = '',
            int $product_tariff = null,
            int $tax_rate_id = null,
            int $family_id = null,
            int $unit_id = null            
        )
        {
            $this->product_sku = $product_sku;  
            $this->product_name = $product_name;
            $this->product_description = $product_description;
            $this->product_price = $product_price;
            $this->purchase_price = $purchase_price;
            $this->provider_name = $provider_name;
            $this->product_tariff = $product_tariff;
            $this->tax_rate_id = $tax_rate_id;
            $this->family_id = $family_id;
            $this->unit_id = $unit_id;
        }
        //relation $family
        public function getFamily(): ?Family
        {
            return $this->family;
        }
        //relation $tax_rate
        public function getTaxrate(): ?TaxRate
        {
            return $this->tax_rate;
        }
        //relation $unit
        public function getUnit(): ?Unit
        {
            return $this->unit;
        }    
        
        public function getProduct_id(): ?string
        {
            return (string)$this->id;
        }
        
        public function setFamily_id(int $family_id): void
        {
            $this->family_id = $family_id;
        }
        
        public function getProduct_sku(): string
        {
            return $this->product_sku;
        }
        
        public function setProduct_sku(string $product_sku): void
        {
            $this->product_sku = $product_sku;
        }
        
        public function getProduct_name(): string
        {
            return $this->product_name;
        }
        
        public function setProduct_name(string $product_name): void
        {
            $this->product_name = $product_name;
        }
        
        public function getProduct_description(): string
        {
            return $this->product_description;
        }
        
        public function setProduct_description(string $product_description): void
        {
            $this->product_description = $product_description;
        }
    
        public function getProduct_price(): float
        {
            return $this->product_price;
        }
        
        public function setProduct_price(float $product_price): void
        {
            $this->product_price = $product_price;
        }
        
        public function getPurchase_price(): float
        {
            return $this->purchase_price;
        }
        
        public function setPurchase_price(float $purchase_price): void
        {
            $this->purchase_price = $purchase_price;
        }
        
        public function getProvider_name(): string
        {
            return $this->provider_name;
        }
        
        public function setProvider_name(string $provider_name): void
        {
            $this->provider_name = $provider_name;
        }
    
        public function setTax_rate_id(int $tax_rate_id): void
        {
            $this->tax_rate_id = $tax_rate_id;
        }
    
        public function getTax_rate_id(): ?int
        {
            return $this->tax_rate_id;
        }
    
        public function setUnit_id(int $unit_id): void
        {
            $this->unit_id = $unit_id;
        }
    
        public function getUnit_id(): ?int
        {
            return $this->unit_id;
        }
    
        public function getFamily_id(): ?int
        {
            return $this->family_id;
        }
        
        public function getProduct_tariff(): int
        {
            return $this->product_tariff;
        }
    
        public function setProduct_tariff(int $product_tariff): void
        {
            $this->product_tariff = $product_tariff;
        }
    }
    

    Version

    ORM 2.0.0 
    Ubuntu PHP 8.1.2, Wampserver PHP 8.1.7
    
    type:bug status:to be verified 
    opened by rossaddison 35
  • Typed property must not be accessed before initialization

    Typed property must not be accessed before initialization

    Try to add php 7.4 property typing to any of the Entity examples from docs and persist it with db, you will get that exception.

    For the reference see also doctrine issue and corresponding PR. As far as I see the issue is partially resolved, see this one.

    Not sure whether the issue in Doctrine was only for id (i.e. primary keys), but here we have the issue for any typed field in Entity.

    type:question magic 
    opened by armpogart 18
  • ManyToMany error Transaction can't be finished. Some relations can't be resolved🐛

    ManyToMany error Transaction can't be finished. Some relations can't be resolved🐛

    What happened?

    У меня есть две сущности `User` и `Tag` со связью `ManyToMany`.

    Если в обоих сущностях указать связь ManyToMany, то возникает ошибка Transaction can't be finished. Some relations can't be resolved

    Для воспроизведения ошибки, я взял ваш тест Cycle\ORM\Tests\Functional\Driver\Common\Relation\ManyToMany\ManyToManyRelationTest и добавил в метод getSchemaArray() связь ManyToMany для Tag::class:

    I have two entities User and Tag related with the ManyToMany relation

    If the ManyToMany relation is specified in both entities, then an error will be thrown with the message Transaction can't be finished. Some relations can't be resolved

    To reproduce that case you can use the Cycle\ORM\Tests\Functional\Driver\Common\Relation\ManyToMany\ManyToManyRelationTest test case and add the ManyToMany relation for the Tag::class (in the getSchemaArray() method) as below:

             Tag::class => [
                    ...
                    Schema::RELATIONS => [
                        'users' => [
                            Relation::TYPE => Relation::MANY_TO_MANY,
                            Relation::TARGET => User::class,
                            Relation::SCHEMA => [
                                Relation::CASCADE => true,
                                Relation::THROUGH_ENTITY => TagContext::class,
                                Relation::INNER_KEY => 'id',
                                Relation::OUTER_KEY => 'id',
                                Relation::THROUGH_INNER_KEY => 'tag_id',
                                Relation::THROUGH_OUTER_KEY => 'user_id',
                            ],
                        ],
                    ],
                ],
    
    Результат выполнения теста `testUnlinkManyToManyAndReplaceSome()`:

    After testUnlinkManyToManyAndReplaceSome() calling you will see that error:

    Cycle\ORM\Exception\TransactionException : Transaction can't be finished. Some relations can't be resolved:
    Create new `tag_context`
     - tag.users:tag_context (Cycle\ORM\Relation\ShadowBelongsTo)
     /app/vendor/cycle/orm/src/Exception/TransactionException.php:40
     /app/vendor/cycle/orm/src/Transaction/UnitOfWork.php:104
     /app/vendor/cycle/orm/src/Transaction.php:48
     /app/app/src/Example/Functional/Driver/Common/BaseTest.php:248
     /app/app/src/Example/Functional/Driver/Common/Relation/ManyToMany/ManyToManyRelationTest.php:403
    

    Version

    ORM 2.0.0
    PHP 8.0
    
    type:bug status:to be verified 
    opened by only-viktor 14
  • refactor: rename constrain to scope

    refactor: rename constrain to scope

    Closes #65

    • Replace "constrain" with "scope" all over the code base
    • Add BC aliases with deprecation replacement suggestion (need to ignore cs warning on alias files)
    opened by hustlahusky 13
  • Filter columns in Select

    Filter columns in Select

    Is there any opportunities for filtering columns rather than select()->buildQuery()->columns()?

    I make some investigation and found that this behaviour can be implemented via implementation of LoaderInterface and so on.

    Am I right or in this library exists other way to do what I want?

    I want this behaviour:

    class TestModel
    {
        /** @Column(type="string")*/
        public $field1;
        /** @Column(type="string")*/
        public $field2;
        /** @Column(type="string")*/
        public $field3;
        
        public function __construct($field1, $field2, $field3)
        {
            $this->field1 = $field1;
            $this->field2 = $field2;
            $this->field3 = $field3;
        }
    }
    
    class TestCase
    {
         public function testSelectFields()
         {
            $t = new Transaction($orm)->persist((new TestModel('1', '2', '3')))
            $t->run();
            $result = $orm->getRepository(TestModel::class)->select()->columns(['field1', 'field2'])->fetchOne();
    
            $this->assertEquals('1', $result->field1);
            $this->assertEquals('2', $result->field2);
            $this->assertNull($result->field3);
         }
    }
    
    opened by mrakolice 11
  • Использование PostgreSQL типа array

    Использование PostgreSQL типа array

    В PostgreSQL можно использовать поля для хранения массивов https://www.postgresql.org/docs/9.1/arrays.html В документации не нашел информации по добавлению кастомных типов полей, поэтому хотел быт уточнить, какие есть способоы добавления новых типов?

    opened by butschster 10
  • STI и изменение типа сущности

    STI и изменение типа сущности

    Всем привет!

    Сегодня столкнулся с новой, интересной задачкой:

    Есть три сущности:

    
    /** @ORM\Entity */
    class User {
        ...
    }
    
    /** @ORM\Entity */
    class Model extends User {
        ...
    }
    
    /** @ORM\Entity */
    class Studio extends User {
        ...
    }
    

    Допустим мне необходимо User конвертировать в Model. Самый простой способ сделать это, грубо говоря, указать нужный тип $user->_type = 'Model'. Но как только мы хотим сделать Model -> Studio, то этот способ уже не прокатит, т.к. mapper вручную _type переопределит. Полагаю единтсвенный способ сделать это - переопределить mapper и в нем этот функционал выпилить.

    По мне идеальным решением было бы иметь некий хелпер, который бы мог заниматсья конвертаций, типа переброски всех полей из одного объекта в другой и при этом корректировать Identity map, чтобы в момент persist'a объект сохранялся в базу как новая сущность.

    opened by butschster 9
  • fetchOne() overrides current entity

    fetchOne() overrides current entity

    I do not know this is by design or not, but I think it is a strange behavior.

    This is my use case:

    I have an entity, and I would like to check this entity exists or not in the database. A simplified example:

    class CustomerRepository
    {
        public function exists($entity)
        {
            /** @var \Cycle\ORM\Select $select */
            $select = $this->select();
            // .. adding conditions based on primary keys
            return $this->fetchOne() !== null;
        }
    }
    

    After calling fetchOne my $entity instance is overridden with the result of fetchOne

    type:bug 
    opened by albertborsos 9
  •  Typed property must not be accessed before initialization

    Typed property must not be accessed before initialization

    Использую PHP 7.4 Обычные сущности для Many To Many. Пытаюсь связать существующие записи. Ругается на типизированное свойство в pivot entity при сохранении. Typed property App\CategoryContractor::$id must not be accessed before initialization

    /**
     * @Cycle\Entity(table="category_contractor")
     */
    class CategoryContractor
    {
        /**
         * @Cycle\Column(type="primary")
         */
        public int $id;
    }
    
    type:question status:wontfix 
    opened by Anlamas 8
  • It doesn't load relation when filtering by column of junction table

    It doesn't load relation when filtering by column of junction table

    For this schema:

        'place' => [
            Schema::ROLE        => 'place',
            Schema::ENTITY      => StrClass::class,
            Schema::MAPPER      => StdMapper::class,
            Schema::DATABASE    => 'default',
            Schema::TABLE       => 'places',
            Schema::PRIMARY_KEY => 'id',
            Schema::COLUMNS     => [
                'id',
                'name'
            ],
            Schema::TYPECAST    => [
                "id" => "int"
            ],
            Schema::SCHEMA      => [],
            Schema::RELATIONS   => [
                'members' => [
                    Relation::TYPE   => Relation::MANY_TO_MANY,
                    Relation::TARGET => 'user',
                    Relation::SCHEMA => [
                        Relation::CASCADE           => true,
                        Relation::THROUGH_ENTITY    => 'place_member',
                        Relation::INNER_KEY         => 'id',
                        Relation::OUTER_KEY         => 'id',
                        Relation::THROUGH_INNER_KEY => 'place_id',
                        Relation::THROUGH_OUTER_KEY => 'user_id'
                    ]
                ]
            ]
        ],
        'place_member' => [
            Schema::ROLE        => 'place_member',
            Schema::ENTITY      => StrClass::class,
            Schema::MAPPER      => StdMapper::class,
            Schema::DATABASE    => 'default',
            Schema::TABLE       => 'place_members',
            Schema::PRIMARY_KEY => 'id',
            Schema::COLUMNS     => [
                'id',
                'user_id',
                'place_id',
                'role_id',
                'period_id'
            ],
            Schema::TYPECAST    => [
                "id" => "int",
                'user_id' => 'int',
                'place_id' => 'int',
                'period_id' => 'int',
                'role_id' => 'int'
            ],
            Schema::SCHEMA      => [],
            Schema::RELATIONS   => [
                'role' => [
                    Relation::TYPE   => Relation::BELONGS_TO,
                    Relation::TARGET => 'roles',
                    Relation::SCHEMA => [
                        RELATION::NULLABLE => true,
                        Relation::CASCADE   => true,
                        Relation::INNER_KEY => 'role_id',
                        Relation::OUTER_KEY => 'id'
                    ]
                ]
            ]
        ]
    ]
    

    When I run this query:

        $place = $cycle
            ->getRepository('place')
            ->select()
            ->load([
                'members' => [ 'as' => 'membersOfThatPeriod', 'where' => [ '@[email protected]_id' => 2 ]], 
                '[email protected]' 
            ])
            ->wherePk(1)
            ->fetchData());
    
    echo $place->members->getPivot($place->members[0])->role; // NULL <--- WRONG!
    

    I know that the schema is OK, because if I remove the [email protected] from the query, it gives me a reference to 'role' with the right id. And doing something like:

    $item = $cycle->>getRepository('place_member')->select()->load('role')->fetchOne(); 
    echo $item->role->name; // display the name of that role corretly.
    
    • Looking at the generated queries, the table roles was never used in any of them.
    type:bug 
    opened by guilhermeaiolfi 8
  • Проблема с выполнением миграций

    Проблема с выполнением миграций

    Привет!

    Сегодня столкнулся с такой проблемой:

    Есть несколько сущностей

    Entities
    -- Order
        -- Status.php
    -- Order.php
    

    Сущность Status.php имеет belongsTo связь с Order.php и при создании миграций схема для Status генерируется раньше чем Order и миграция падает из-за того, что внешние ключи не могут найти таблицу orders.

    Пока я вижу только один вариант - Переименовать Status в OrderStatus и вынести из папки Order, но может есть еще какие либо варианты? Составлять схему вручную в конфиге наверно будет не лучшее предложение, мы пользуемся аннотациями.

    opened by butschster 8
  • Use Reference objects in HasMany and ManyToMany relations

    Use Reference objects in HasMany and ManyToMany relations

    Hello @roxblnfk does that mean that the only way to create a new record that has a ManyToMany to existing records is to load those existing records and assign them to the ManyToMany property? This would have a pretty severe scalability issue in some cases.

    Can you think of a workaround, like exposing a OneToMany relationship to the join table and using references to it when saving/updating a record?

    Our API allows a user to give an array of primary keys for many to many relationships, we then would ideally create reference objects for each of these IDs instead of loading them into memory just to create the relationship.

    Thanks

    Originally posted by @longshadowdev in https://github.com/cycle/orm/discussions/338#discussioncomment-3659342

    type:feature 
    opened by roxblnfk 0
  • 🐛 Automatic table aliases do not enter the postgres limit (63 bytes)

    🐛 Automatic table aliases do not enter the postgres limit (63 bytes)

    No duplicates 🥲.

    • [X] I have searched for a similar issue in our bug tracker and didn't find any solutions.

    What happened?

    SQLSTATE[42712]: Duplicate alias: 7 ERROR:  table name \"longtablename1_longtablename2_longtablename3_thispartwastruncatedbypostgres\" specified more than once
    

    Possible solution 1:

    I can use table aliases when I select records from repository with loadand with methods but I can't set up an alias for orderBy/Where clause for an entity attributes.

    Possible solution 2 (correct):

    ORM can use non-human-friendly aliases like t1, t2, t3 ... etc

    Version

    ORM 2.2.0
    PHP 8.1
    
    type:bug status:ready for adoption 
    opened by roquie 0
  • 💡Efficiently load morphed relations

    💡Efficiently load morphed relations

    I have an idea!

    Say we have a media morphed relation of comment entity. (e.g media could be photo, video, embed, etc)

    I would like to fetch comments and also be able to write:

    $commentRepository
        ->select()
        ->load('media')
        ->fetchAll()
    

    Here, cycle should first load all comments, then separately group and fetch morphed media_type from their corresponding tables and then merge them all back to the comments.

    type:feature 
    opened by rauanmayemir 1
  • 🐛 EM::persistState inserts the same entity twice

    🐛 EM::persistState inserts the same entity twice

    No duplicates 🥲.

    • [X] I have searched for a similar issue in our bug tracker and didn't find any solutions.

    What happened?

    Entity manager inserts the same entity twice if the entity has persisted using the persistState method

    
    $import = $orm->make('import');
    
    $em->persistState($import)->run();
    $em->persistState($import)->run();
    

    Error

    [Cycle\Database\Exception\StatementException\ConstrainException]
    SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint "import_pkey"
    DETAIL:  Key (id)=(60) already exists.
    

    Version

    ORM 2.2.0
    PHP 8.1
    
    type:bug status:ready for adoption 
    opened by roxblnfk 0
  • Pivot table in orderBy💡

    Pivot table in orderBy💡

    I have an idea!

    It is possible to refer to the pivot table with '@' in where(), however '@' can not be used in orderBy(). And this is just what I need! I want to order Tags by a column 'ord' in the pivot table.

    type:feature 
    opened by sjaakp 1
  • Add ODKU behavior or delete childs before adding them

    Add ODKU behavior or delete childs before adding them

    product has many productSkus

    SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-kg' for key 'mt_product_sku.mt_product_sku_index_product_id_attribute_name_61a108014425b'   
    (1-kg ,"1" is product id and "kg" is attribute name)
    
    string(194) "INSERT INTO `mt_product_sku` (`sequence`, `status`, `created_at`, `updated_at`, `ip_address`, `product_id`, `attribute_name`, `weight`, `price`, `quantity`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
    

    the right action should be delete the same rows or ON DUPLICATE KEY UPDATE

    Originally posted by @TiaNex-Com in https://github.com/cycle/orm/discussions/342

    type:bug 
    opened by roxblnfk 0
Releases(v2.2.0)
  • v2.2.0(Jul 5, 2022)

    What's Changed

    • Add supporting for loophp/collection by @drupol (#344)
    • Add supporting for PHP 8.1 Enum in the default typecast handler Cycle\ORM\Parser\Typecast by @roxblnfk (#352)
    • Improve template annotations in Cycle\ORM\Select\Repository and Cycle\ORM\Select classes by @roxblnfk (#351)
    • Classes Cycle\ORM\Transaction\UnitOfWork and Cycle\ORM\Transaction\Runner are now not internal by @roxblnfk (#353)

    New Contributors

    • @drupol made their first contribution in https://github.com/cycle/orm/pull/344

    Full Changelog: https://github.com/cycle/orm/compare/v2.1.1...v2.2.0

    Source code(tar.gz)
    Source code(zip)
  • v2.1.1(Jun 5, 2022)

    What's Changed

    • Remove $config property overriding in the RelationConfig by @msmakouz (#343)
    • Fix bug on ManyToMany resolving by @roxblnfk and @albertborsos (#345)

    New Contributors

    • @albertborsos made their first contribution in https://github.com/cycle/orm/pull/336

    Full Changelog: https://github.com/cycle/orm/compare/v2.1.0...v2.1.1

    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Mar 3, 2022)

    What's Changed

    • Remove final from the Select class by @msmakouz (#327)
    • Fix keys comparing in the BelongsTo relation by @msmakouz (#326)
    • Add Psalm @template annotations to RepositoryInterface by @roxblnfk

    Full Changelog: https://github.com/cycle/orm/compare/v2.0.2...v2.1.0

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Jan 27, 2022)

  • v2.0.1(Jan 20, 2022)

    What's Changed

    • Fix protected relation fields hydration on eager loading by @roxblnfk in https://github.com/cycle/orm/pull/314

    Full Changelog: https://github.com/cycle/orm/compare/v2.0.0...v2.0.1

    Source code(tar.gz)
    Source code(zip)
  • v1.8.1(Jan 17, 2022)

    What's Changed

    • Add the STI discriminator autoadding in the Schema by @gam6itko (#278)
    • Extract origin in the HasMany::queue() when it's instance of Collection by @roxblnfk (#277)
    • Fix lazy loading sorting by @msmakouz (#300)
    • Up min version of laminas-hydrator by @msmakouz (#310)

    New Contributors

    • @gam6itko made their first contribution in https://github.com/cycle/orm/pull/278

    Full Changelog: https://github.com/cycle/orm/compare/v1.8.0...v1.8.1

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Dec 22, 2021)

    • Minimal PHP version is 8.0
    • Composited keys
    • 'Joined Table Inheritance' and 'Single Table Inheritance'
    • Added ProxyMapper (Cycle\Orm\Mapper\Mapper)
    • Supporting for arrays/Doctrine/Laravel or custom collections in HasMany and ManyToMany relations
    • Typecasting moved to Mappers
    • Added Typecast handlers with Castable/Uncastable interfaces
    • Added Entity Manager and Unit Of Work instead of Cycle\ORM\Transaction
    • A lot of Interfaces are changed
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Nov 28, 2021)

    • Added ORM::with. Other ORM::with* methods marked as deprecated (#257)
    • Better compatibility between ConstrainInterface and ScopeInterface (#271)
    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Nov 4, 2021)

  • v1.7.0(Nov 2, 2021)

    • Update the Node data comparison mechanism (#235)
    • Fix Entity data comparison with objects in fields (#234)
    • Add ability for relations to independently determine related value changing (#227)
    Source code(tar.gz)
    Source code(zip)
  • v1.6.1(Oct 13, 2021)

  • v1.6.0(Sep 8, 2021)

  • v1.5.1(Aug 6, 2021)

  • v1.5.0(Jul 1, 2021)

    • Hotfix: fixed type assertions for mapped criteria keys (#187)
    • Hotfix: inner keys naming in morphed relations (#192)
    • Refactor: prevent repeating entity hydration in the Many to Many relations (#188)
    • Added deprecation for SchemaInterface::CONSTRAIN. Use SchemaInterface::SCOPE instead (#194)
    Source code(tar.gz)
    Source code(zip)
  • v1.4.2(May 12, 2021)

  • v1.4.1(Apr 2, 2021)

  • v1.4.0(Mar 31, 2021)

    • Added support of Doctrine/Annotations v2 by @roxblnfk
    • Bugfix: prevent merge nodes with same roles when initializing pivot entity by @hustlahusky
    • Bugfix: RefersTo and BelongTo relations innerKey naming error by @roxblnfk
    • Added 'orderBy' option for relations by @roxblnfk
    • Fixed ID mapping column is set and differs from the field name by @roxblnfk
    Source code(tar.gz)
    Source code(zip)
  • v1.3.3(Feb 12, 2021)

    • fixed issue with redundant UPDATE when updating entity state in cyclic relations (related to TimestampedMapper)
    • fixed issue causing typed (7.4+) entities to fail in cycling many to many relations
    • entity re-load refreshes the entity state and relations instead of keeping the original entity
    • minor optimizations in many to many relations
    • added PHP8 test pipelines
    Source code(tar.gz)
    Source code(zip)
  • v1.3.2(Feb 4, 2021)

  • v1.3.1(Dec 24, 2020)

  • v1.3.0(Dec 23, 2020)

  • v1.2.17(Dec 4, 2020)

  • v1.2.16(Nov 27, 2020)

  • v1.2.15(Nov 2, 2020)

  • v1.2.14(Nov 2, 2020)

  • v1.2.13(Oct 23, 2020)

  • v1.2.12(Jul 30, 2020)

  • v1.2.11(Jul 22, 2020)

  • v1.2.10(Jul 16, 2020)

  • v1.2.9(Jun 24, 2020)

    • fixed bug causing ORM to disable relation graph pointing to Promises in related entities
    • more promise related tests
    • adds getTarget to RelationInterface
    Source code(tar.gz)
    Source code(zip)
Owner
Cycle ORM
PHP DataMapper ORM and Data Modelling Engine by SpiralScout
Cycle ORM
[READ-ONLY] A flexible, lightweight and powerful Object-Relational Mapper for PHP, implemented using the DataMapper pattern. This repo is a split of the main code that can be found in https://github.com/cakephp/cakephp

CakePHP ORM The CakePHP ORM provides a powerful and flexible way to work with relational databases. Using a datamapper pattern the ORM allows you to m

CakePHP 146 Sep 28, 2022
Spot v2.x DataMapper built on top of Doctrine's Database Abstraction Layer

Spot DataMapper ORM v2.0 Spot v2.x is built on the Doctrine DBAL, and targets PHP 5.4+. The aim of Spot is to be a lightweight DataMapper alternative

Spot ORM 601 Aug 9, 2022
Propel2 is an open-source high-performance Object-Relational Mapping (ORM) for modern PHP

Propel2 Propel2 is an open-source Object-Relational Mapping (ORM) for PHP. Requirements Propel uses the following Symfony Components: Config Console F

Propel 1.2k Sep 29, 2022
Ouzo Framework - PHP MVC ORM

Ouzo is a PHP MVC framework with built-in ORM and util libraries. PHP 8.0 or later is required. We believe in clean code and simplicity. We value unit

Ouzo 70 Aug 7, 2022
Simple Enum cast for Eloquent ORM using myclabs/php-enum.

Enum cast for Eloquent Simple Enum cast for Eloquent ORM using myclabs/php-enum. Requirements PHP 7.3 or higher Laravel 8.0 or higher Installation You

Orkhan Ahmadov 5 Apr 21, 2022
The Enobrev\ORM library is a small framework of classes meant to be used for simply mapping a mysql database to PHP classes, and for creating simply SQL statements using those classes.

The Enobrev\ORM library is a small framework of classes meant to be used for simply mapping a mysql database to PHP classes, and for creating simply SQL statements using those classes.

Mark Armendariz 0 Jan 7, 2022
Doctrine Object Relational Mapper (ORM)

3.0.x 2.9.x 2.8.x Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence for PHP objects. It sits on top o

Doctrine 9.4k Sep 27, 2022
Baum is an implementation of the Nested Set pattern for Laravel's Eloquent ORM.

Baum Baum is an implementation of the Nested Set pattern for Laravel 5's Eloquent ORM. For Laravel 4.2.x compatibility, check the 1.0.x branch branch

Estanislau Trepat 2.2k Sep 27, 2022
ORM layer that creates models, config and database on the fly

RedBeanPHP 5 RedBeanPHP is an easy to use ORM tool for PHP. Automatically creates tables and columns as you go No configuration, just fire and forget

Gabor de Mooij 2.2k Sep 28, 2022
A drop-in Doctrine ORM 2 implementation for Laravel 5+ and Lumen

Laravel Doctrine ORM A drop-in Doctrine ORM 2 implementation for Laravel 5+ $scientist = new Scientist( 'Albert', 'Einstein' ); $scientist->a

Laravel Doctrine 771 Sep 26, 2022
Extensions for the Eloquent ORM

Sofa/Eloquence Easy and flexible extensions for the Eloquent ORM. Currently available extensions: Searchable query - crazy-simple fulltext search thro

Jarek Tkaczyk 1.1k Sep 27, 2022
Builds Cycle ORM schemas from OpenAPI 3 component schemas

Phanua OpenAPI 3 + Jane + Cycle ORM = ?? Phanua builds Cycle ORM schemas from OpenAPI 3 component schemas. Released under the MIT License. WARNING: Th

Matthew Turland 5 Aug 1, 2021
Extra RedBean ORM

RedBeanPHP 5 RedBeanPHP is an easy to use ORM tool for PHP. Automatically creates tables and columns as you go No configuration, just fire and forget

GingTeam Development 4 Nov 12, 2021
Articulate - An alternative ORM for Laravel, making use of the data mapper pattern

Articulate Laravel: 8.* PHP: 8.* License: MIT Author: Ollie Read Author Homepage: https://ollie.codes Articulate is an alternative ORM for Laravel bas

Ollie Codes 4 Jan 4, 2022
MongoDB ORM that includes support for references,embed and multilevel inheritance.

Introduction Features Requirements Installation Setup Database Basic Usage - CRUD Relationship - Reference Relationship - Embed Collection Inheritance

Michael Gan 203 Sep 23, 2022
Low code , Zero Configuration ORM that creates models, config, database and tables on the fly.

?? ARCA ORM ?? Low code , Zero Configuration ORM that creates models, config, database and tables on the fly. ?? ???? Made in India ???? Complete docu

Scrawler Labs 23 Aug 14, 2022
TO DO LIST WITH LOGIN AND SIGN UP and LOGOUT using PHP and MySQL please do edit the _dbconnect.php before viewing the website.

TO-DO-LIST-WITH-LOGIN-AND-SIGN-UP TO DO LIST WITH LOGIN AND SIGN UP and LOGOUT using PHP and MySQL please do edit the _dbconnect.php before viewing th

Aniket Singh 2 Sep 28, 2021
The lightweight PHP database framework to accelerate development

The lightweight PHP database framework to accelerate development Features Lightweight - Less than 100 KB, portable with only one file Easy - Extremely

Angel Lai 4.6k Sep 23, 2022
Easy-to-use PDO wrapper for PHP projects.

EasyDB - Simple Database Abstraction Layer PDO lacks brevity and simplicity; EasyDB makes separating data from instructions easy (and aesthetically pl

Paragon Initiative Enterprises 704 Sep 29, 2022