Doctrine Object Relational Mapper (ORM)

Related tags

orm
Overview
3.0.x 2.9.x 2.8.x
Build status Build status Build status
Coverage Status Coverage Status Coverage Status

Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL), inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility without requiring unnecessary code duplication.

More resources:

Issues
  • Value objects (Based on #634)

    Value objects (Based on #634)

    This is PR #634 with the following additional changes:

    • Merged into master (fixed some conflict in Metadata classes)
    • Support for DQL queries on fields of embedded objects
    opened by schmittjoh 77
  • Fix the

    Fix the "Erroneous data format for unserializing" error message

    cf http://www.doctrine-project.org/jira/browse/DDC-3120

    opened by marmotz 71
  • [WIP] Nullable embedded objects.

    [WIP] Nullable embedded objects.

    The idea was to have a simple (and clean) way to override the nullable property of embedded objects, so I've added the nullable attribute on the @Embedded annotation and it have 3 possible values:

    • NULL: The nullable option that was defined on the attributes of the embeddable class won't be overriden;
    • TRUE: All attributes of the embeddable class will be marked as nullable and the embeddable instance only would be created when data is not NULL;
    • ~~FALSE: All attributes of the embeddable class will be marked as non-nullable.~~

    There's a lot of things to be improved (mostly on UnitOfWork), but it's fully working with basic tests as you can see on ValueObjectsTest::testCRUDOfNullableEmbedded() case.

    I would appreciate a lot your opinions!

    Delayed WIP 
    opened by lcobucci 60
  • DDC-3480: ORM\Embeddable does not create ManyToOne column in the database

    DDC-3480: ORM\Embeddable does not create ManyToOne column in the database

    Jira issue originally created by user tvoslar:

    Following Embeddable

    /****
     * @ORM\Embeddable
     */
    class Address
    {
        /****
         * @ORM\ManyToOne(targetEntity="Country")
         */
        protected $country;
    

    won't save country attribute into the database table, other simple attributes (like type="text") saved normally.

        /****
         * @ORM\Embedded(class="LuciniLucini\Adsender\CommonBundle\Entity\Address")
         */
        private $address;
    
    Bug 
    opened by doctrinebot 56
  • Doctrine schema update command shows always few queries to be executed

    Doctrine schema update command shows always few queries to be executed

    I am using doctrine with symfony and run php bin/console doctrine:schema:update --force command. But it executes few queries always as following:

    ALTER TABLE company CHANGE current_subscription_id current_subscription_id INT DEFAULT NULL, CHANGE city city VARCHAR(255) DEFAULT NULL, CHANGE state state VARCHAR(255) DEFAULT NULL, CHANGE zip zip VARCHAR(255) DEFAULT NULL, CHANGE country country VARCHAR(255) DEFAULT NULL, CHANGE phone phone VARCHAR(255) DEFAULT NULL, CHANGE subscription_start_date subscription_start_date DATE DEFAULT NULL, CHANGE subscription_end_date subscription_end_date DATE DEFAULT NULL;

    Invalid Missing Tests 
    opened by jigarpancholi 50
  • [WIP] Value objects

    [WIP] Value objects

    This pull request takes a different approach than GH-265 to implement ValueObjects. Instead of changing most of the code in every layer, we just inline embedded object class metadata into an entities metadata and then use a reflection proxy that looks like "ReflectionProperty" to do the rewiring.

    The idea is inspired from Symfony Forms 'property_path' option, where you can write and read values to different parts of an object graph.

    This is a WIP, there have been no further tests made about the consequences of this approach. The implementation is up for discussion.

    opened by beberlei 47
  • DDC-3120: Warning: Erroneous data format for unserializing PHP5.6+

    DDC-3120: Warning: Erroneous data format for unserializing PHP5.6+

    Jira issue originally created by user techkey:

    Hi all,

    There seems to be something strange going on in the method newInstance() of the class \Doctrine\ORM\Mapping\ClassMetadataInfo.

    The original class method looks like this:

    {quote}\Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance(){quote}

        {
            if ($this->_prototype === null) {
                $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
            }
    
            return clone $this->_prototype;
        }
    

    What happens now when a class that implements \Serializable is that a "Warning: Erroneous data format for unserializing" shows up and the function unserialize() returns false.

    That is because a class that implements \Serializable is expected to have the letter 'C' in the serialize string instead of the letter 'O'.

    I've made a quick work-around like this:

    {quote}\Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance(){quote}

        {
            if ($this->_prototype === null) {
                $this->_prototype = @unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
                if ($this->_prototype === false) {
                    $this->_prototype = unserialize(sprintf('C:%d:"%s":0:{}', strlen($this->name), $this->name));
                }
            }
    
            return clone $this->_prototype;
        }
    

    That seems to work in my isolated tests and with Symfony2 and Doctrine2 and FOSUserBundle together.

    I've noticed this because the Model\User class from FOSUserBundle implements \Serializable.

    I had to implement a check in Model\User class because when using {{'C:%d:"%s":0:{}'}} the $serialized parameter of the unserialize method in the Model\User class is a empty string then.

    That warning seems only to happen with PHP5.6+. PHP5.5.12 and below doesn't show that warning.

    I hope someone can shine some light on this, thank you,

    Cornelis.

    Bug 
    opened by doctrinebot 46
  • Introduce `getIterable()` on AbstractQuery

    Introduce `getIterable()` on AbstractQuery

    I do not fancy accessing index 0 ([0]) while iterating iterable result from iterate() to get the entity.

    $results = $em->select('e')->from('entity')->getQuery()->iterate();
    foreach($resuls as $result) {
       $entityIsHere = $result[0];
    }
    

    So was thinking to introduce new method that gets rid of the index and returns the result same way as getResult() does. Only with the change that the new behaviour would keep row-by-row hydration.

    $generator = $em->select('e')->from('entity')->getQuery()->toIterable();
    foreach($generator as $result) {
       $entityIsHere = $result;
    }
    

    This change deprecates AbstractQuery::iterate and follow up PRs renamed the new method toIterable().

    • [x] Implement new row by row hydrating iterator
    • [x] Test the shapes are the same
    • [x] Add separate tests
    • [x] Find name for new method

    Follow ups:

    • https://github.com/doctrine/orm/pull/8268
    • https://github.com/doctrine/orm/pull/8293
    opened by simPod 46
  • Efficient counting on Criteria

    Efficient counting on Criteria

    Hi,

    This is an attempt to solve this very annoying issue: http://www.doctrine-project.org/jira/browse/DDC-2217

    I'm not sure about my solution as I'm not really into Doctrine internals.

    Use case

    I have a library that is based exclusively on Criteria API. A Paginator adapter uses an empty Criteria to count how many elements are in the collection. However, EntityRepository's matching method always initialize the whole collection into an ArrayCollection. This is unusable in most cases and make the API unusable for my use case.

    Solution

    I've created a new LazyCollectionCriteria that implements an efficient count. I think the cleanest solution would be to add a method to the Selectable interface: with a count method. But I think this is not possible now, unfortunately.

    If the solution seems nice to you, I'll write the tests.

    ping @ocramius, @macnibblet and @thinkscape (this should make ZfrRest usable :D)

    opened by bakura10 45
  • DDC-93: It would be nice if we could have support for ValueObjects

    DDC-93: It would be nice if we could have support for ValueObjects

    Jira issue originally created by user ablock:

    class User {
        /****
         * @Column(type="string")
         */
        private $address;
    
        /****
         * @Column(type="string")
         */
        private $city;
    
        /****
         * @Column(type="string")
         */
        private $state;
    }
    

    We could have:

    class User {
        /****
         * @Component(class="Address")
         */
         private $address;
    }
    

    It would my life a lot easier....


    Notes for implementation

    Value objects can come in two forms:

    a) as embedded value objects b) as collections of value objects

    An implementation should concentrate on a) first. The following things all concentrate on a).

    DQL Support

    Conditions:

    1. "select f from Foo f where f.embedded.value = ?1" (setParameter(1, $scalarValue))
    2. "select f from Foo f where f.embedded = ?1" (setParameter(1, $embeddedValueObject))

    At least Nr.1 must be possible in a first implementation.

    Selecting:

    1. "select f from Foo f" must explode embedded value objects in the SQL SELECT clause.
    2. "select f.embedded from Foo f" must explode the columns of the embedded object in the SQL SELECT clause.

    At least Nr. 1 must be possible in a first implementation, obviously.

    Components affected (among others): Parser, SqlWalker, ...

    Persisters

    The persisters need to take embedded value objects into account when persisting as well as loading entities.

    Components affected (among others): Persisters, UnitOfWork, ...

    Metadata

    ClassMetadataInfo needs to be extended with a field (probably an array) that contains the mappings of embedded values. New annotations as well as XML/YAML elements are needed.

    Components affected (among others): ClassMetadataInfo, AnnotationDriver, YamlDriver, XmlDriver, doctrine-mapping.xsd, ...

    Change Tracking

    If value objects are supposed to be immutable this is easy and might require no or few changes. If, however, we want to track changes in mutable value objects it might get more complicated.

    Components affected (among others): UnitOfWork, ...

    opened by doctrinebot 45
  • Remove template from method signature

    Remove template from method signature

    If $className is a class-string, then we return an instance of that class. However, if it's an alias, things get complicated, and it's hard to tell. There does not seem to be a way to express that for now.

    We should probably consider dropping namespace aliases entirely and add support for ::class inside DQL if it's not the case already.

    Refs #8767 , https://github.com/phpstan/phpstan/issues/5175 , cc @VincentLanglet

    Bug 
    opened by greg0ire 4
  • default_second_level_cache.region_cache_driver does not exist. after 2.9

    default_second_level_cache.region_cache_driver does not exist. after 2.9

    After updating, I am having an error due to a setting configuration that I do not understand. Does anyone else have this problem? were you able to find any solution?

    The service alias "doctrine.orm.default_second_level_cache.region_cache_driver" does not exist.

    opened by SacreDPamiR 0
  • Throw exception on unsupported mappings in Embeddable

    Throw exception on unsupported mappings in Embeddable

    For 3.0 mapping drivers should be more strict on which annotations/attributes are not allowed on properties / classes. For example currently you can define assocations on Embeddable but they are just ignored by drivers. For 2.x we could start deprecating this behavior and then throw a mapping exception in 3.0.

    Deprecation Improvement 
    opened by beberlei 3
  • Tests for MappingDriver::isTransient

    Tests for MappingDriver::isTransient

    The AbstractMappingDriverTest has no generic tests for isTransient, we now introduced some for AttributeDriverTest in #8756 - maybe this can be generalized and improved for all drivers.

    Improvement 
    opened by beberlei 0
  • It seems that this option is not handled by Doctrine : #[OneToOne( cascade: [

    It seems that this option is not handled by Doctrine : #[OneToOne( cascade: ["persist","remove"])].

    Trying to update an entity schema mapped with php8 attributes but the cascade option isn't passed on the DB

    opened by jonascarfantan 1
  • Invalid multiple primary keys

    Invalid multiple primary keys

    Hello. I have 2 primary keys: ID and blob UUID. And have 2 entities User and Article. Then for Article i generate relation ManyToOne and have code:

    class User
    {
        /**
         * @ORM\Id
         * @ORM\GeneratedValue
         * @ORM\Column(type="integer")
         */
        private $id;
    
        /**
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="NONE")
         * @ORM\Column(type="uuid", unique=true, nullable=false)
         */
        private $uuid;
    
        /**
         * @ORM\OneToMany(targetEntity=Article::class, mappedBy="user",)
         */
        private $articles;
     }
    
    class Article
    {
        /**
         * @ORM\ManyToOne(targetEntity=User::class, inversedBy="articles")
         * @ORM\JoinColumn(nullable=false, referencedColumnName="uuid", name="user_uuid")
         */
        private $user;
    }
    

    Problem is that i have invalid mapping:

    php bin/console doctrine:schema:validate   
    
    Mapping
    -------
    
     [FAIL] The entity-class App\Entity\Article mapping is invalid:
     * The join columns of the association 'user' have to match to ALL identifier columns of the target entity 'App\Entity\User', however 'id, uuid' are missing.
    
    
    Database
    --------
    
                                                                                                                            
     [OK] The database schema is in sync with the mapping files.                                                            
                                                                                                                            
    

    Is it a bug or am I do something wrong? Thanks!

    opened by RSalo 1
  • orm:schema-tool:update Execution plan fails due to ignoring existing fk constraints (mysql)

    orm:schema-tool:update Execution plan fails due to ignoring existing fk constraints (mysql)

    I'm converting the following entity from using dedicated PK to composite PK by removing the id column. From:

    /**
    * @Entity
    * @Table(
    * 	name="data",
    *	uniqueConstraints={@UniqueConstraint(name="data_unique", columns={"channel_id", "timestamp"})}
    * )
    */
    class Data
    {
        /**
        * @Id
        * @Column(type="integer", nullable=false)
        * @GeneratedValue(strategy="IDENTITY")
        */
        protected $id;
    
        /**
        * @Column(type="bigint", nullable=false)
        */
        protected $timestamp;
    
        /**
        * @Column(type="float", nullable=false)
        */
        protected $value;
    
        /**
        * @ManyToOne(targetEntity="Channel", inversedBy="data")
        * @JoinColumn(name="channel_id", referencedColumnName="id", nullable=false)
        */
        protected $channel;
    }
    

    To:

    /**
    * @Entity
    * @Table(name="data")
    */
    class Data
    {
        /**
        * @Id
        * @ManyToOne(targetEntity="Channel", inversedBy="data")
        * @JoinColumn(name="channel_id", referencedColumnName="id")
        */
        protected $channel;
    
        /**
        * @Id
        * @Column(type="bigint")
        */
        protected $timestamp;
    
        /**
        * @Column(type="float", nullable=false)
        */
        protected $value;
    }
    

    This creates the following execution plan:

    ALTER TABLE data MODIFY id INT NOT NULL;
    DROP INDEX data_unique ON data;
    ALTER TABLE data DROP PRIMARY KEY;
    ALTER TABLE data DROP id, CHANGE channel_id channel_id INT NOT NULL;
    ALTER TABLE data ADD PRIMARY KEY (channel_id, timestamp);
    

    The plan fails intermittendly due to

    In PDOConnection.php line 132:
    
      [PDOException (HY000)]
      SQLSTATE[HY000]: General error: 1832 Cannot change column 'channel_id': used in a foreign key constraint 'FK_ADF3F36372F5A1AA'
    

    It seems that ManyToOne Fk relation is not handled properly when changing the underlying columns.

    opened by andig 3
  • left join with codition may return wrong data

    left join with codition may return wrong data

    step1: query dql:

    SELECT web, webUrl FROM App\Entity\Web web LEFT JOIN web.webUrl webUrl WITH webUrl.md5 = [MD51] WHERE web.name = [NAME1]

    [MD51] is not exist

    query result got a Web with no WebUrl.

    step2: create a WebUrl with [MD51]

    step3: query same dql at step1

    SELECT web, webUrl FROM App\Entity\Web web LEFT JOIN web.webUrl webUrl WITH webUrl.md5 = [MD52] WHERE web.name = [NAME1]

    with same :name but different :md5

    [MD52] is not exist

    query result got a Web with a WebUrl but it is wrong and created by step2.

    `

    by the way md5 is a unique index field.

    $query = $this->getEntityManager()->createQueryBuilder(); $query->from(Web::class, 'web'); $query->leftJoin('web.webUrl', 'webUrl', Join::WITH, 'webUrl.md5 = :md5')->setParameter('md5', $md5); $query->where('web.name = :name')->setParameter('name', $name); $query->select('web', 'webUrl'); $web = $query->getQuery()->getOneOrNullResult();

    opened by sunchuo 0
  • orm:schema-tool:update Execution plan not optimal when replacing primary key (mysql)

    orm:schema-tool:update Execution plan not optimal when replacing primary key (mysql)

    I'm converting the following entity from using dedicated PK to composite PK by removing the id column. From:

    /**
    * @Entity
    * @Table(
    * 	name="data",
    *	uniqueConstraints={@UniqueConstraint(name="data_unique", columns={"channel_id", "timestamp"})}
    * )
    */
    class Data
    {
        /**
        * @Id
        * @Column(type="integer", nullable=false)
        * @GeneratedValue(strategy="IDENTITY")
        */
        protected $id;
    
        /**
        * @Column(type="bigint", nullable=false)
        */
        protected $timestamp;
    
        /**
        * @Column(type="float", nullable=false)
        */
        protected $value;
    
        /**
        * @ManyToOne(targetEntity="Channel", inversedBy="data")
        * @JoinColumn(name="channel_id", referencedColumnName="id", nullable=false)
        */
        protected $channel;
    }
    

    To:

    /**
    * @Entity
    * @Table(name="data")
    */
    class Data
    {
        /**
        * @Id
        * @ManyToOne(targetEntity="Channel", inversedBy="data")
        * @JoinColumn(name="channel_id", referencedColumnName="id")
        */
        protected $channel;
    
        /**
        * @Id
        * @Column(type="bigint")
        */
        protected $timestamp;
    
        /**
        * @Column(type="float", nullable=false)
        */
        protected $value;
    }
    

    This creates the following execution plan:

    ALTER TABLE data MODIFY id INT NOT NULL;
    DROP INDEX data_unique ON data;
    ALTER TABLE data DROP PRIMARY KEY;
    ALTER TABLE data DROP id, CHANGE channel_id channel_id INT NOT NULL;
    ALTER TABLE data ADD PRIMARY KEY (channel_id, timestamp);
    

    This plan seems not optimal as it needs to lock and copy the entire data table in steps 1,3,4. My assumption is that steps one and 3 could be combined into one step and potentially running step 2 after step 5 might be a nop.

    opened by andig 0
  • empty objects

    empty objects

    I always get empty objects. It seems like it can't read the getters, probably I'm missing something in the configuration...

    https://prnt.sc/14lq3mu https://prnt.sc/14lpvh0

    opened by saemsev 1
Releases(2.9.3)
Owner
Doctrine
The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object mapping.
Doctrine
Doctrine2 behavioral extensions, Translatable, Sluggable, Tree-NestedSet, Timestampable, Loggable, Sortable

Doctrine Behavioral Extensions This package contains extensions for Doctrine ORM and MongoDB ODM that offer new functionality or tools to use Doctrine

Doctrine Extensions 3.5k Jun 13, 2021
Doctrine2 behavioral extensions, Translatable, Sluggable, Tree-NestedSet, Timestampable, Loggable, Sortable

Doctrine Behavioral Extensions This package contains extensions for Doctrine ORM and MongoDB ODM that offer new functionality or tools to use Doctrine

Doctrine Extensions 3.6k Jun 18, 2021
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 8.6k Jun 16, 2021
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 728 Jun 10, 2021
[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 140 May 5, 2021
PHP DataMapper, ORM

Cycle ORM Cycle is PHP DataMapper, ORM and Data Modelling engine designed to safely work in classic and daemonized PHP applications (like RoadRunner).

Cycle ORM 852 Jun 17, 2021
Doctrine Database Abstraction Layer

Doctrine DBAL 4.0-dev 3.0 2.13 N/A N/A Powerful database abstraction layer with many features for database schema introspection, schema management and

Doctrine 8.1k Jun 11, 2021
Convention-based Object-Relational Mapper

Corma Corma is a high-performance, convention-based ORM based on Doctrine DBAL. Corma is great because: No complex and difficult to verify annotations

Michael O'Connell 28 May 8, 2021
ATK Data - Data Access Framework for high-latency databases (Cloud SQL/NoSQL).

ATK Data - Data Model Abstraction for Agile Toolkit Agile Toolkit is a Low Code framework written in PHP. Agile UI implement server side rendering eng

Agile Toolkit 245 Jun 14, 2021
A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5.

Idiorm http://j4mie.github.com/idiormandparis/ Feature/API complete Idiorm is now considered to be feature complete as of version 1.5.0. Whilst it wil

Jamie Matthews 2k Jun 20, 2021
Doctrine2 behavior traits

Doctrine Behaviors This PHP library is a collection of traits and interfaces that add behaviors to Doctrine entities and repositories. It currently ha

KNP Labs 800 Jun 16, 2021
:gem: Simple MySQLi Abstraction Layer + Doctrine/DBAL support

?? Simple MySQLi Class This is a simple MySQL Abstraction Layer compatible with PHP 7+ that provides a simple and secure interaction with your databas

Lars Moelleken 34 Jan 9, 2021
Psalm Stubs for doctrine/mongodb-odm library

doctrine-mongodb-psalm-plugin A Doctrine plugin for Psalm (requires Psalm v4). Installation: $ composer require --dev runtothefather/doctrine-mongodb-

Evgeny 5 Apr 12, 2021
🔌 A Doctrine DBAL Driver implementation on top of Swoole Coroutine PostgreSQL extension

Swoole Coroutine PostgreSQL Doctrine DBAL Driver A Doctrine\DBAL\Driver implementation on top of Swoole\Coroutine\PostgreSQL. Getting started Install

Leo Cavalcante 9 May 29, 2021