[DDC-1309] Doctrine_Collection toArray() does not return results of table joins. Created: 01/Aug/11  Updated: 01/Aug/11  Resolved: 01/Aug/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Sharn White Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

e.g.
$doctrineCollection = Doctrine_Query::create()
->from('Table1 a')
->innerJoin('a.Table2 b ON a.id = b.id')
->execute();

$doctrineCollection->toArray() will return only the contents of Table1. However, $doctrineCollection->getFirst()->toArray() will return the results of Table1 + an additional key named 'Table2' which returns the join result from Table2.

It does not make sense for the collection hydration to differ to that of the objects in the collection.



 Comments   
Comment by Sharn White [ 01/Aug/11 ]

If this is intended you can go ahead and trash this issue. Just doesn't seem right to me.

Comment by Sharn White [ 01/Aug/11 ]

Nevermind. I should have been setting $deep to true.





[DDC-1285] Select by multiple ids Created: 22/Jul/11  Updated: 11/Sep/13  Resolved: 11/Sep/13

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: None
Fix Version/s: 2.1, 2.2
Security Level: All

Type: Improvement Priority: Major
Reporter: Serge Smertin Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   

How do you look at adding findByIds(array $ids) to EntityManager and UnitOfWork? This would allow fetching multiple entities from a database at one request and would be very useful for caching - there would be even some kind of IdentityMap kept in memcached or any other caching engine, that supports multiple id retrieval: i've been using sujhjhjch an architecture in multiple projects and it turned out to be very effective. There were two basic methods - findIdsByFilter(array $filter) and findEntitiesByIds(array $ids). The latter one had a caching proxy, replicating entities to a cache storage. If this idea proceeds - I'd be glad to cover it with more details.

This topic on StackOverflow could also help:
http://stackoverflow.com/questions/276709/design-pattern-for-memcached-data-caching



 Comments   
Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version

Comment by Benjamin Eberlei [ 11/Sep/13 ]

This is implemented on the Repository since 2.1 or 2.2 with findBy(array('id' => array(1, 2, 3, 4, 5));





[DDC-1281] ORM uses BasicEntityPersister instead of JoinedSubclassPersister on a JOINED inheritance Created: 19/Jul/11  Updated: 01/Aug/11  Resolved: 01/Aug/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Daniel Lima Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None
Environment:

Database server: Oracle 10, Debian
PHP: 5.3.6
Apache: 2.2.18 (Windows 7 Home Premium)



 Description   

Hi,
I have these classes: https://gist.github.com/1085518/58b5424bc0ab5af1ae65421fe832e7a1b45533cf (read the comments to see the stracktrace)

If I try:
$entity = $em->find('Usuario', $id);
$entity->getPessoaFisica()->getId();
I got this error: Class does not exist.

This is looking weird because, analyzing the stacktrace, the ORM loads the proxy through the BasicEntityPersister instead of JoinedSubclassPersister.

I've been discussed about this on: http://groups.google.com/group/doctrine-user/browse_thread/thread/190dc2c4b768ae13#

Regards,
Daniel Lima



 Comments   
Comment by Benjamin Eberlei [ 26/Jul/11 ]

It seems your mappings are wrong, the @JoinColumn maps to a column named COD_PERFIL_USUARIO, but that is not the ID of the Joined Entity base class.

Comment by Daniel Lima [ 01/Aug/11 ]

There was a wrong column definition on discriminator column:

On the DATABASE was: CHAR(30).

The hydrator filled discriminator column with "F " or "J " (with blank spaces), making it impossible to Discriminator map to locate the related classes.

I think it´s a bug with OCI driver or Doctrine´s Hydrator.

Comment by Benjamin Eberlei [ 01/Aug/11 ]

That is how oracle works. It right pads chars.





[DDC-1270] Incorrect QueryBuilder example Created: 11/Jul/11  Updated: 01/Apr/14  Resolved: 01/Apr/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Documentation Priority: Major
Reporter: Alex Bogomazov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In the QueryBuilder section of the documentation (http://www.doctrine-project.org/docs/orm/2.1/en/reference/query-builder.html#the-expr-class) there's an example with statements like

 
$qb->expr()->select('u')

But this doesn't work anymore.



 Comments   
Comment by Michael Ridgway [ 11/Jul/11 ]

PR at https://github.com/doctrine/orm-documentation/pull/35

Comment by Steve Müller [ 01/Apr/14 ]

Fixed in commit: https://github.com/doctrine/orm-documentation/commit/c0860a6018698701c63c80bf8c62e2be7b2c9268





[DDC-1239] Using a repository with composite keys generates invalid SQL Created: 30/Jun/11  Updated: 30/Jun/11  Resolved: 30/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Kyle Spraggs Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Ubuntu 11.04 (standard LAMP stack), PHP 5.3, MySQL 5.x, Apache 2


Attachments: File Clinic.php     File Consumer.php    

 Description   

Invalid SQL is generated when using composite keys along with Repository methods (fineOneBy, etc). Everything works properly when using createQuery() to generate DQL manually.

Working:
$q = $this->_em
->createQuery(
"SELECT c,c2,g FROM Entity\OAuth\Consumer c LEFT JOIN c.group g LEFT JOIN c.clinic c2 WHERE c.key = '{$consumer_key}'");
$this->_consumer = $q->getSingleResult();

Invalid:
$this->_consumer = $this->_em->getRepository('Entity\OAuth\Consumer')
->findOneBy(array('key' => $consumer_key));

Generated SQL for "invalid" method:
SELECT ... FROM oauth_consumer t0 LEFT JOIN groop t10 ON t0.groupId = t10.id LEFT JOIN company t17 ON t0.companyId = t17.id LEFT JOIN clinic t28 ON t0.dsid = t28.dsid t0.rid = t28.rid LEFT JOIN user t50 ON t0.userId = t50.id WHERE t0.`key` = ?

Notice the missing AND in the query above. I've attached the entities in question.



 Comments   
Comment by Benjamin Eberlei [ 30/Jun/11 ]

Fixed





[DDC-1238] Proxy query executed, but object not initialized Created: 29/Jun/11  Updated: 04/Jul/11  Resolved: 04/Jul/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Benjamin Eberlei [ 04/Jul/11 ]

Fixed, nasty issue with lazy loading and $em->clear()





[DDC-1233] Minor spellcheck in UnitOfWork Created: 27/Jun/11  Updated: 28/Jun/11  Resolved: 28/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Trivial
Reporter: Alexandre Mathieu Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

On UnitOfWork, line 580:
. " on the relationship. If you cannot find out which entity casues the problem"

should be:

. " on the relationship. If you cannot find out which entity causes the problem"



 Comments   
Comment by Benjamin Eberlei [ 28/Jun/11 ]

Fixed





[DDC-1231] In ObjectHydrator->_getEntity(...) looking for the discriminator should be in uppercase Created: 27/Jun/11  Updated: 28/Jun/11  Resolved: 28/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Blocker
Reporter: Alexandre Mathieu Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

On line 204:
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];

$this->_rsm->discriminatorColumns[$dqlAlias] is in lowercase, whereas $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]] is in uppercase.

$discrColumn cannot be assigned.

A simple fix could be:
$discrColumn = $this->_rsm->metaMappings[strtoupper($this->_rsm->discriminatorColumns[$dqlAlias])];



 Comments   
Comment by Benjamin Eberlei [ 27/Jun/11 ]

What version of the code are you using? I fixed this problem yesterday on git master.

Comment by Alexandre Mathieu [ 27/Jun/11 ]

2.1.0RC1 downloaded this morning from the website.

Comment by Benjamin Eberlei [ 27/Jun/11 ]

ah yes, please update to Git Master then or wait for the RC2 release happening this week.

Comment by Benjamin Eberlei [ 28/Jun/11 ]

This was fixed on master





[DDC-1230] entity state is not set to STATE_REMOVED when removing an entity Created: 27/Jun/11  Updated: 28/Jun/11  Resolved: 28/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.0.7, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The UnitOfWork never sets the state to STATE_REMOVED in the map when scheduling an entity for delete. This means that the UnitOfWork will never tell you that the entity is in STATE_REMOVED when asking for its state but will return STATE_MANAGED



 Comments   
Comment by Benjamin Eberlei [ 28/Jun/11 ]

Fixed





[DDC-1227] On 2.1 upgrade QueryBuilder incompatability getAlias() when using ''->add('select', 'sample')->add('from', 'Samply sample') instead of ->select('sample')->from('Sample', 'sample') Created: 23/Jun/11  Updated: 25/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Philip Leicht Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

ubuntu 10.10, php 5.3.5,



 Description   

In queryBuilder if I use the add function when adding components to the query I get an error like this :

Fatal error: Call to a member function getAlias() on a non-object in /usr/local/zend/share/pear/Doctrine/ORM/QueryBuilder.php on line 989

sample code is

$this->em->createQueryBuilder()
		    ->add('select', 'sample')
		    ->add('from', 'Sample sample')
		    ->getQuery()
		    ->execute()

it works with the following:

$this->em->createQueryBuilder()
		    ->select('sample')
		    ->from('Sample', 'sample')
		    ->getQuery()
		    ->execute()

I apologize if this is a duplicate ticket. I would like to see this fixed in the final release of 2.1 before installing it in our production environment.



 Comments   
Comment by Benjamin Eberlei [ 25/Jun/11 ]

Formatting

Comment by Benjamin Eberlei [ 25/Jun/11 ]

Fixed, thanks! You qualify for a mug/t-shirt after 2.1 release





[DDC-1226] OneToOne Unidirectional entities not persisting Created: 23/Jun/11  Updated: 23/Jul/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Garrett Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-1228 Unidirectional OneToOne Associations ... Resolved

 Description   

We have the following three entities:

User
Participant
Profile

... Users and Participants are two distinctly different things in our system and each has a Profile. Currently we use OneToOne unidirectional associations to "map" the User to it's Profile and a Participant to it's Profile. So far (2.0) we've been able to do the following:

$profile = $user->getProfile();
$profile->setLastName('Doe');
$em->persist($profile);
$em->flush();

...and the profile is saved. In 2.1 rc1 this no longer works.

After some testing it was determined that 2.1 is requiring that our Profile refer back to each object (bidirectional). Now, this may not be the best example but imagine we had another entity that wanted to make use of a Profile, we'd rather not have to explicitly add the reference back for each entity that wants to use it just to get it persisted.

Again, in 2.0 our setup worked fine and so far I've been unable to find any documentation pointing to this sort of thing.



 Comments   
Comment by Benjamin Eberlei [ 25/Jun/11 ]

Is this relation marked as FETCH=EAGER? Can you post the mapping files of User and Profile please?

Comment by Benjamin Eberlei [ 25/Jun/11 ]

I could reproduce this issue now.

Comment by Benjamin Eberlei [ 25/Jun/11 ]

Fixed

Comment by Erik Hauters [ 23/Jul/11 ]

how do you mean? Fixed? Where can I find this fix?





[DDC-1224] QueryBuilder delete issues CREATE TEMPORARY TABLE error on PostgreSQL Created: 22/Jun/11  Updated: 26/Jun/11  Resolved: 26/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.0.7, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Rafael Kassner Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PostgreSQL 8.4



 Description   

When I try to issue a delete an Class Table Inheritance Entity using QueryBuilder and I'm using schemas on tablename (for Postgres), I got the following error from postgres:

SQLSTATE[42P16]: Invalid table definition: 7 ERROR: temporary tables cannot specify a schema name

This occurs because Doctrine\ORM\Mapping\ClassMetadataInfo::getTemporaryIdTableName() returns just "$this->table['name'] . '_id_tmp'", and when my entity is declared with @Table(name="feed.tb_feed"), obviously I will got error.

Temporary tables are created in a special schema in Postgres, and I'm thinking to convert the tablename from the class metadata from feed.tb_feed to feed_tb_feed into the getTemporaryIdTableName method with a single str_replace. That works for Postgres, but I don't mind what can happen in another DBMS.

Any suggestions?



 Comments   
Comment by Benjamin Eberlei [ 26/Jun/11 ]

Fixed





[DDC-1223] STI Inheritance Mapping Exception suggests to mark Entity abstract when initialization is not required, how to realize this? Created: 22/Jun/11  Updated: 25/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Menno Holtkamp Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I have an abstract PHP class 'PartyAbstract' that uses Single Table Inheritance with a discriminator map to distinguish between a number of classes that extend the 'PartyAbstract' class. The 'PartyAbstract' class itself is not an entry in that discriminator map. Annotations are used to define the discriminator map.

 
/**
* @Entity
* @Table(schema="public", name="party")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discriminator", type="integer")
* @DiscriminatorMap({
* "1" = "Project\Entity\Party\PartyType1",
* "2" = "Project\Entity\Party\PartyType2",
* "3" = "Project\Entity\Party\PartyType3"
* })
abstract class PartyAbstract{}

As of version 2.1.0-rc1, the following exception is thrown:

 
"Entity 'Project\Entity\PartyAbstract' has to be part of the descriminator map of 'Project\Entity\PartyAbstract' to be properly mapped in the inheritance hierachy. If you want to avoid instantiation of this type mark it abstract."

My question is: how can I mark this Entity abstract? I DO want to be able to count the complete number of Parties, but instantiation of the PartyAbstract class is never required. The use of @MappedSuperclass is not allowed here, or together with the @Entity annotation...

PS: also not that the message in the exception contains two typo's

  • 'descriminator' vs 'discriminator'
  • 'hierachy' vs 'hierarchy'


 Comments   
Comment by Benjamin Eberlei [ 25/Jun/11 ]

This way:

/**
* @Entity
* @Table(schema="public", name="party")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discriminator", type="integer")
* @DiscriminatorMap({
* "0" = "Project\Entity\Party\PartyAbstract",
* "1" = "Project\Entity\Party\PartyType1",
* "2" = "Project\Entity\Party\PartyType2",
* "3" = "Project\Entity\Party\PartyType3"
* })
Comment by Menno Holtkamp [ 25/Jun/11 ]

Aah, ok, that was the way I 'resolved' it, but the exception message confused me as it suggests that it requires a configuration setting to 'mark it abstract'. Maybe the following message can avoid this confusion:

"Entity 'Project\Entity\PartyAbstract' has to be part of the discriminator map of 'Project\Entity\PartyAbstract' to be properly mapped in the inheritance hierarchy. If you want to avoid instantiation of this type, make it an abstract class"

Thanks for the swift response!





[DDC-1222] Composite Primary Key is not recognized Created: 21/Jun/11  Updated: 21/Jun/11  Resolved: 21/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   

I have the following mapping:

class TopicTranslation
{
    /**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Topic")
*/
    private $topic;

    /**
* @ORM\Id
* @ORM\Column(type="string", length=5)
*/
    private $locale;
}

Doctrine will only use "locale" as primary key for the table. I would expect it to use "topic_id" and "locale" instead.



 Comments   
Comment by Johannes Schmitt [ 21/Jun/11 ]

Fixed in D 2.1





[DDC-1221] Fatal Error when building a query using ->add() instead of ->from() Created: 21/Jun/11  Updated: 25/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When creating a query using $qb->add('from', ...) instead of $qb->from(...) a fatal error is thrown when building the DQL query line 989 of the QueryBuilder because this line assumes it has a Doctrine\ORM\Query\Expr\From instance whereas it gets a string.

Note that a similar issue was fixed for $qb->getRootAlias: http://www.doctrine-project.org/jira/browse/DDC-1140



 Comments   
Comment by Christophe Coevoet [ 21/Jun/11 ]

Note that this issue has been introduced by https://github.com/doctrine/doctrine2/commit/905e05cd361e9702325e3ea26224b95ac4f7d2e0

Comment by Benjamin Eberlei [ 25/Jun/11 ]

This is fixed, thanks for reporting this regression.





[DDC-1218] Generator disappear with mappedSuperclass and in others common inheritance's cases Created: 21/Jun/11  Updated: 27/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Nicolas Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Symfony



 Description   

With mapped superclass the id lost autoincrement. I've test with yaml and annotation this is the same.

An example with yaml entities :

 
Document:
  type: mappedSuperclass
  fields:
    mimetype: { type: string, length: 255 }
    filename: { type: string, length: 255 }

Image:
  type: entity
  fields:
    id: { type: integer, id: true, generator: { strategy: AUTO } }

The id in the table Image lost autoincrement.



 Comments   
Comment by Nicolas [ 22/Jun/11 ]

The problem is in file doctrine/lib/Doctrine/ORM/Mapping, a solution, with just one change could be
:

    protected function loadMetadata($name)
    {
        if ( ! $this->initialized) {
...
        // Move down the hierarchy of parent classes, starting from the topmost class
...
            // Invoke driver
            try {
                $this->driver->loadMetadataForClass($className, $class);
            } catch (ReflectionException $e) {
                throw MappingException::reflectionFailure($className, $e);
            }
//Change
            if ($parent) {
//To
            if ($parent && ! $parent->isInheritanceTypeNone()) {
//EndChange
                if ($parent->isIdGeneratorSequence()) {
...
        }
Comment by Nicolas [ 23/Jun/11 ]

I have seen the resolution in doctrine later version, so i hesitate to close this issue.

But i'm sure that the solution in place will not resolve all situation.

By example, if the superclass isn't mapped but an entity with joined, this doesn't work properly, and you lost the id and the generator of the childclass. Another exemple, you want a mapped with generator, and subclass which don't indicate id, you can't the generator isn't include, and the id is required in the subclass.

The code actually work just for same table proposition, and not good, because with same table you must indicate an not used id in the child class ( why an id is an obligation!!!, Sql permit to have table without id).

If somebody read this, i propose a solution for inherited class with another schema,

Each propositions are with a class inheriting from superclass :

Schema for joinedclass.

In this case generator are leave in the same functions

table_class
  class_id -> *self generator*
table_link
  class_id
  class_discriminent
  superclass_id
table_superclass
  superclass_id -> *self generator*

or better and closest from the actual solution ( with obligation to have different id name)

table_class
  class_id -> *self generator*
  superclass_id
table_superclass
  superclass_id -> *self generator*
  discriminator

Schema for same table

Not exactly the actual behavior but very near

table_class
   class_id autogenerate (or not exist)
   superclass_id (autogenerate with concatenation class_id and discr or not exit)

The better for me :

table_class
    superclass_id

Schema for mapped

table_class
  class_id  <--- if exist (not obligatory)
  superclass_id <--- if class_id not exist, the generator from superclass_id
                                    if class_id exist, the generator from class_id

Even with there ideas, the possibility to have more than one generator method could be usefull. (i know that autoincrement can be use just one time). A solution, could be to add generator to field an not to entity in a first time, and treat generator at the end of the process not in the same place that the fields.

So if you read this thank and aufwiedersehen.

Comment by Menno Holtkamp [ 23/Jun/11 ]

This seems to relate to an issue I created at: http://www.doctrine-project.org/jira/browse/DDC-1218

Comment by Benjamin Eberlei [ 25/Jun/11 ]

Fixed

Comment by Nicolas [ 27/Jun/11 ]

Thanks





[DDC-1214] Call to undefined method Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand::getFullName() Created: 19/Jun/11  Updated: 19/Jun/11  Resolved: 19/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Andrew W Bender Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The getFullName() method has been removed from the latest Symfony\Component\Console\Command\Command class and is causing the above error on line 131 of UpdateCommand.php



 Comments   
Comment by Benjamin Eberlei [ 19/Jun/11 ]

Fixed





[DDC-1212] Exception of mapping of ID generation strategy Created: 16/Jun/11  Updated: 16/Jun/11  Resolved: 16/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Gustavo Falco Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Apache 2.2.16
PHP 5.3.3
Ubuntu 11



 Description   

Hi all,

After updating today Doctrine 2 from master branch I'm getting:

Entity of type "Entity" is missing an assigned ID. The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called. If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.

Was there a change on the mapping of ID generation strategy? I was using a commit of the master branch from 1 o 2 weeks ago and it was working ok. I took a look at the repo for changes on the last days but I couldn't find anything related to this.

I paste the mapping and entities here:

Element:

/**
 * @ORM\MappedSuperclass
 */
abstract class Element
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;
}

File:

/**
 * @ORM\Entity
 * @ORM\Table(name="file")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({
        "image"  = "Image",
    })
 */
abstract class File extends Element
{
     // Fields
}

And Image:

/**
 * @ORM\Entity
 * @ORM\Table(name="image")
 */
class Image extends File
{
     // Fields
}

Thanks in advance!



 Comments   
Comment by Benjamin Eberlei [ 16/Jun/11 ]

Do you "use" the mapping AS ORM namespace?

Comment by Gustavo Falco [ 16/Jun/11 ]

Yes, sorry for not including that. I had to add this to my entities 1 o 2 weeks ago when I updated all my vendors:

use Doctrine\ORM\Mapping as ORM;

Is it still right?

Comment by Benjamin Eberlei [ 16/Jun/11 ]

Fixed

Comment by Gustavo Falco [ 16/Jun/11 ]

Great!

I want to say just in case BTW that removing the mapped superclass and moving all its fields to, for example, "File" makes the error go away.

Thanks a lot!





[DDC-1211] Expr::literal problem with numeric value 0 Created: 16/Jun/11  Updated: 19/Jun/11  Resolved: 19/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: Git Master
Fix Version/s: 2.0.7, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Gustavo Falco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None
Environment:

Apache 2.2.16
PHP 5.3.3
Ubuntu 11



 Description   

Hi,

I'm using master branch of Doctrine 2. Including an Expr with a numeric 0 value (not a string):

$value = 0;

$qb->expr()->gte($field, $qb->expr()->literal($value));

Expr::literal method will return an empty string ('') instead of '0', which causes that this expression be something like:

entity.myField >=  

instead of:

entity.miField >= '0''

This makes the query fail. Tracking the issue down I've found this on Expr\Base::add method:

    public function add($arg)
    {
         if ( ! empty($arg) || ($arg instanceof self && $arg->count() > 0)) {
            // If we decide to keep Expr\Base instances, we can use this check
            if ( ! is_string($arg)) {
                $class = get_class($arg);

                if ( ! in_array($class, $this->_allowedClasses)) {
                    throw new \InvalidArgumentException("Expression of type '$class' not allowed in this context.");
                }
            }

            $this->_parts[] = $arg;
        }
    }

The problem is that empty function returns true if you pass '0', so a call to Expr\Base::add would end on NOT adding '0' to $this->_parts array. That's why it finally returns ''.

I wanted to make the fix for this but I'm having issues running the phing build task. Which are the steps to follow to run the tests? Running phing build task I get on the "test" task:

Could not create task/type: 'nativephpunit'. Make sure that this class has been declared using taskdef / typedef.

Thanks!



 Comments   
Comment by Benjamin Eberlei [ 19/Jun/11 ]

Assigned to guilherme, i suppose we could change the !empty($arg) to $arg !== null ?

Comment by Benjamin Eberlei [ 19/Jun/11 ]

Fixed





[DDC-1209] DateTime (and other custom object types) cannot be used in primary key (singular or composite) Created: 15/Jun/11  Updated: 14/Sep/12  Resolved: 16/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Michael Ridgway Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

This bug was encountered using a DateTime type as an @Id, but it appears that it will affect any type of custom data type if it is an object.

Doctrine\ORM\Id\AssignedGenerator checks to see if the key is an object. If so it does a look up in the identity map to find the object, but in the case of DateTime it will not find it and throws an exception. It is appears this is the case for both singular and composite keys as shown in the attached test.

Offending code: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Id/AssignedGenerator.php#L52

Test case forthcoming.



 Comments   
Comment by Michael Ridgway [ 15/Jun/11 ]

Test case: https://github.com/mridgway/doctrine2/blob/DDC-1209/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1209Test.php

Comment by Michael Ridgway [ 16/Jun/11 ]

I posted a fix and it was merged this morning by Guilherme: https://github.com/doctrine/doctrine2/pull/74

Comment by Jonathan Ingram [ 11/Sep/12 ]

I am wondering if this fix is working correctly or has regressed?

I have a YAML file as follows:

 
Acme\Entity\SearchExecution:
    type: entity
    table: search_execution
    id:
        search:
            associationKey: true
        # It seems this is not working
        dateExecuted:
            type: datetime
            column: Date
    fields:
        executionTime:
            type: integer
    manyToOne:
        search:
            targetEntity: Acme\Entity\Search
            joinColumn:
                name: SearchID
                referencedColumnName: id
        user:
            targetEntity: Acme\Entity\User
            joinColumn:
                name: ByUserID
                referencedColumnName: id

So the "dateExecuted" field is used to compose an artificial primary key since the table has no PK.

The error is:

[ErrorException]                                                                                                                                                                                
  Catchable Fatal Error: Object of class DateTime could not be converted to string in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1295

Exception trace:
 () at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1295
 Symfony\Component\HttpKernel\Debug\ErrorHandler->handle() at n/a:n/a
 implode() at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1295
 Doctrine\ORM\UnitOfWork->addToIdentityMap() at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1125
 Doctrine\ORM\UnitOfWork->scheduleForInsert() at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:810
 Doctrine\ORM\UnitOfWork->persistNew() at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1540
 Doctrine\ORM\UnitOfWork->doPersist() at vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1501
 Doctrine\ORM\UnitOfWork->persist() at vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:565
 ...

In my composer.json, the relevant versions of Doctrine are:

    {
        {
            "package": "doctrine/common",
            "version": "2.3.0-RC1"
        },
        {
            "package": "doctrine/dbal",
            "version": "2.3.x-dev",
            "source-reference": "239630b61f03f39d198441eced1bfffb7b0e61d1",
            "commit-date": "1346866589"
        },
        {
            "package": "doctrine/orm",
            "version": "2.3.0-RC1"
        },
    }

Is this a bug or am I misusing this?

Comment by Christophe Coevoet [ 13/Sep/12 ]

this has never been supported. Doctrine 2 has always required id fields to be castable as string, which is not the case of a DateTime object

Comment by Jonathan Ingram [ 14/Sep/12 ]

But didn't the PR https://github.com/doctrine/doctrine2/pull/74 get merged in https://github.com/doctrine/doctrine2/commit/98bc3c4e402731fae8716e99c7c19d5e0ff7b60a ? And you can see the use of @Id in the test cases, e.g. https://github.com/doctrine/doctrine2/commit/98bc3c4e402731fae8716e99c7c19d5e0ff7b60a#L2R78 ?





[DDC-1204] Single Table Inheritance - Columns of one hierarchy are dropped Created: 13/Jun/11  Updated: 15/Jun/11  Resolved: 15/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In the following example, the columns of the classes B, C, D are not in the database schema. Only those of the classes A and E.

/**
 * @ORM\Entity
 * @ORM\Table(name = "a")
 * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string", length=20)
 * @ORM\DiscriminatorMap({
 *     "c"   = "C",
 *     "d"   = "D",
 *     "e"   = "E"
 * })
 */
abstract class A { }

/**
 * @ORM\Entity
 */
abstract class B extends A { }

/**
 * @ORM\Entity
 */
class C extends B { }

/**
 * @ORM\Entity
 */
class D extends B { }

/**
 * @ORM\Entity
 */
class E extends A { }


 Comments   
Comment by Johannes Schmitt [ 13/Jun/11 ]

The problem here is that class B is not part of the discriminator map which was necessary due to issue #DDC-1203. So, once that is resolved this can likely be closed as well.

Comment by Benjamin Eberlei [ 15/Jun/11 ]

Fixed





[DDC-1203] Single Table Inheritance - Discriminator Column is not populated Created: 12/Jun/11  Updated: 30/Jun/11  Resolved: 18/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Johannes Schmitt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: JPEG File graph.jpg    

 Description   

I have the following class inheritance; if I have the mapped super class in there, the discriminator column is not populated; if I remove it, it is correctly set.

/**
 * @ORM\Entity
 * @ORM\Table(name = "a")
 * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string", length=20)
 * @ORM\DiscriminatorMap({
 *     "c"   = "C",
 *     "d"   = "D"
 * })
 */
abstract class A { }

/**
 * @ORM\MappedSuperClass
 */
abstract class B extends A { }

/**
 * @ORM\Entity
 */
class C extends B { }

/**
 * @ORM\Entity
 */
class D extends B { }


 Comments   
Comment by Benjamin Eberlei [ 18/Jun/11 ]

This was fixed or something.

Comment by Nikolai Spassoff [ 30/Jun/11 ]

The following hierarchy doesn't work after commit 5ff44b5ec75f6d716ec3.

The thrown exception is:
'Entity\AbstractMaschine' has to be part of the descriminator map of 'Entity\Inventory'

Inventory is just a plain abstract class which contains the @Id field and a few methods used by all subclasses.

Comment by Benjamin Eberlei [ 30/Jun/11 ]

Yes, please add it to the discriminator map, it is necessary for internal algorithms that this class is in the map.

Comment by Benjamin Eberlei [ 30/Jun/11 ]

Ok this has been changed, its not necessary for abstract classes anymore.





[DDC-1196] EntityGenerator: made it work with Doctrine Common 3.0.x Created: 05/Jun/11  Updated: 15/Jun/11  Resolved: 15/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Fabien Potencier Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The entity generator does not work with the new Doctrine Common 3.0.x.

Issue is reported here in Symfony: https://github.com/symfony/symfony/issues/1083

PR that fixes the issue here: https://github.com/doctrine/doctrine2/pull/61






[DDC-1194] Problem using Instance of feature Created: 03/Jun/11  Updated: 10/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.5
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Hernan Rajchert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Ubuntu



 Description   

Hi, i get this error message when executing a query with INSTANCE OF.
Notice: Undefined index: \model\PeopleTaskRecommendFriends in /usr/share/php/Doctrine/ORM/Query/SqlWalker.php on line 1626

The query to be executed is this:

                $query = $this->_em->createQuery("SELECT pt
                                          FROM \model\PeopleTask pt
                                          WHERE pt instance of \model\PeopleTaskRecommendFriends
                                          ");

The query actually being executed is this:

SELECT t0_.int_people_task_id AS int_people_task_id0, t0_.int_people_id AS int_people_id1, t0_.dtm_creation AS dtm_creation2, t0_.bit_completed AS bit_completed3, t0_.vch_names AS vch_names4, t0_.int_task_type_id AS int_task_type_id5 FROM tbl_xref_people_task t0_ WHERE (t0_.int_task_type_id = '') AND t0_.int_task_type_id IN ('1', '2')

The first problem is that for some reason its translating the query with a wrong where clause, so of course no data is returned.

Here is the model

------------------------------------------ Base class----------------------------------------
/**
 * @Entity(repositoryClass="repository\PeopleTaskRepository")
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="int_task_type_id", type="integer")
 * @DiscriminatorMap({1 = "PeopleTaskRecommendFriends", 2 = "PeopleTaskAddBadge"})
 * @Table(name="tbl_xref_people_task")
 */
abstract class PeopleTask extends BaseModel {
 
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer") */
    protected $int_people_task_id;
 
    /** @Column(type="integer") */
    protected $int_people_id;
 
    /** @Column(type="datetime") */
    protected $dtm_creation;
 
    /** @Column(type="bit")*/
    protected $bit_completed;
 
    /** @Column(length=255) */
    protected $vch_names;
 
}
 
----------------------------------------------------Children class-----------------------------------------------
 
/**
 * @Entity(repositoryClass="repository\peopleTask\PeopleTaskRecommendFriendsRepository")
 */
class PeopleTaskRecommendFriends extends PeopleTask {
 /* some methods */
 
}
 


 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

A fix for this is probably just ommitting the prefix \ infront of the model in the DQL. Class Names in Strings are ALWAYS fully qualified, therefore the leading slash has to be omitted.

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Improved error handling when in "a INSTANCE OF b" the classes a and b are unrelated.

Comment by Hernan Rajchert [ 10/Jun/11 ]

Thanks, that did solve my problem.

On a related note, for the original query i had to do this:
$qb->andWhere('pt INSTANCE OF '.$task_type);
instead of this
$qb->andWhere('pt INSTANCE OF :taskType');
$qb->setParameter('taskType', $task_type);

because it complains about the parameter not being a metadata type, and i couldnt find a way to get the metadata type.





[DDC-1193] cascadeRemove misses associations due to proxy not being initialized Created: 03/Jun/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.5, Git Master
Fix Version/s: 2.0.6, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Illya Klymov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Linux x86_64


Attachments: File DDC1193Test.php    
Issue Links:
Dependency
depends on DDC-733 Implement a way of forcing a Persiste... Resolved

 Description   

Let's assume you have two One-to-One relations A>B>C (all include cascade remove). You are deleting object A, while object B is not initialized (and so it will be a proxy). In that case the object C is not deleted because UOW misses relation B>C since proxy of B is not initialized



 Comments   
Comment by Illya Klymov [ 03/Jun/11 ]

Test case. Expected to be put into Tests/ORM/Functional/Ticket folder

Comment by Illya Klymov [ 03/Jun/11 ]

Right now i'm using this hack inside of UOW:

diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 90d3117..a4891c7 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -1702,7 +1702,10 @@ class UnitOfWork implements PropertyChangedListener
             if ( ! $assoc['isCascadeRemove']) {
                 continue;
             }
-            //TODO: If $entity instanceof Proxy => Initialize ?
+            if ($entity instanceof Proxy) {
+                // We need to initialize entity if we do not miss it's relations
+                $entity = clone($entity);
+            }
             $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
             if ($relatedEntities instanceof Collection || is_array($relatedEntities)) {
                 // If its a PersistentCollection initialization is intended! No unwrap!
}}

As stated by beberlei IIRC, we should add public method to the generated proxy class "__doctrineInitializeProxy" or something

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Fixed and merged into 2.0.x





[DDC-1192] fix undefined variable in join-column section of xml driver Created: 03/Jun/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.1
Fix Version/s: 2.0.6, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

$name is undefined, It might be that the fix is as simple as foreach ($manyToOneElement->

{'join-columns'}->{'join-column'} as $name => $joinColumnElement) {
but I'm not sure


if (isset($manyToOneElement->{'join-column'})) {
$joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'});
} else if (isset($manyToOneElement->{'join-columns'}

)) {
foreach ($manyToOneElement->

{'join-columns'}

->

{'join-column'}

as $joinColumnElement) {
if (!isset($joinColumnElement['name']))

{ $joinColumnElement['name'] = $name; }

$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
}
}




 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

This is a copy paste error from the YAML Driver, i fixed it.





[DDC-1191] fix the notices when converting between different mappings Created: 03/Jun/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

https://github.com/doctrine/doctrine2/pull/62
https://github.com/doctrine/doctrine2/pull/63



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Merged





[DDC-1190] Update the doctrine mapping schma in such way it will allow extending the final xml with data from different vendors Created: 03/Jun/11  Updated: 15/Jun/11  Resolved: 15/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I've already made a PR
https://github.com/doctrine/doctrine2/pull/64



 Comments   
Comment by Benjamin Eberlei [ 15/Jun/11 ]

This was implemented.





[DDC-1184] ORM\Id\AssignedGenerator try to current() on non-array Created: 30/May/11  Updated: 11/Jun/11  Resolved: 11/Jun/11

Status: Closed
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Slam Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: None


 Description   
// Doctrine\ORM\AssignedGenerator::generate at line 54

$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));

$value may also be new, so getEntityIdentifier returns NULL and current(NULL) generates an E_WARNING.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Optimized error handling

Comment by Slam [ 08/Jun/11 ]

Error optimizing is welcome but this does not resolve the issue.

Again, if $value is new object, for example a new Entity\User with an empty protected $id:

if (is_object($value)) {
	if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
		throw ORMException::entityMissingForeignAssignedId($entity, $value);
	}
	
	// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
	$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
} else {
	$identifier[$idField] = $value;
}

will ALWAYS throw an exception in the case the Entity is new.

In my projects, i resolved with

if (is_object($value)) {
	if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
		$identifier[$idField] = null;
	} else {
	
		// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
		$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
	}
} else {
	$identifier[$idField] = $value;
}

I have not unit-tested the solution (i'm sorry) and I think a more accurate investigation is needed.

Comment by Benjamin Eberlei [ 11/Jun/11 ]

Please read:

http://www.doctrine-project.org/docs/orm/2.0/en/tutorials/composite-primary-keys.html#general-considerations

This is a necessary requirement, that means if you want to create two entities with a composite pk key of the one depending on the other you have to use two flush operations when using MySQL Auto Increment Keys. This will work with PostgreSQL or Oracle Sequences, but not with Auto increment keys.

Comment by Slam [ 11/Jun/11 ]

Ok, roger.

Just one note: you must know that both two entities are STATE_NEW, because if you try to getEntityState($dependentEntity), UnitOfWork.php:2155 will throw a E_RECOVERABLE_ERROR because the $independentEntity could not be converted to a string (because it has no id).





[DDC-1179] Allow to specify namespace prefix in combination with --from-database Created: 27/May/11  Updated: 11/Jun/11  Resolved: 11/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Minor
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

See https://github.com/symfony/symfony/issues/1119#comment_1247346



 Comments   
Comment by Alexander [ 03/Jun/11 ]

Added this feature:
https://github.com/asm89/doctrine2/commit/7ee8dc4e44e3a761b8dab23a18ded74c9f10d7a3

It depends on the changes made before:
http://www.doctrine-project.org/jira/browse/DDC-1168

The pull request including both tickets:
https://github.com/doctrine/doctrine2/pull/59





[DDC-1176] Error on proxy loading with foreign Key Created: 27/May/11  Updated: 11/Jun/11  Resolved: 11/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Blocker
Reporter: Jonathan Clus Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Doctrine 2.1Beta



 Description   

Look at this thread:http://groups.google.com/group/doctrine-user/browse_thread/thread/2a03a6aea43428d6

This entity class configuration:

class IndividualsStatus
{
    /**
     * @var Individuals
     *
     * @Id
     * @ManyToOne(targetEntity="Individuals", inversedBy="diagnosers", cascade={"persist","refresh","remove"})
     * @JoinColumns({
     *   @JoinColumn(name="individuals_id", referencedColumnName="id")
     * })
     */
    private $individuals;

    /**
     * @var Diagnosers
     *
     * @Id
     * @ManyToOne(targetEntity="Diagnosers", inversedBy="individuals", cascade={"persist","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="diagnosers_id", referencedColumnName="id")
     * })
     */
    private $diagnosers;

    /**
    * @var smallint $status
    *
    * @Column(name="status_individuals", type="smallint")
    */
    private $statusIndividuals;

    [...]
}

class Individuals
{
    /**
     * @var Users
     *
     * @OneToOne(targetEntity="Users", cascade={"persist","detach","merge","refresh","remove"}, orphanRemoval=true)
     * @JoinColumns({
     *   @JoinColumn(name="users_id", referencedColumnName="id", unique=true)
     * })
     */
    private $users;

    /**
     * @var Advertisements
     *
     * @OneToMany(targetEntity="Advertisements", mappedBy="individuals")
     */
    private $advertisements;

    /**
     * @var IndividualsStatus
     *
     * @OneToMany(targetEntity="IndividualsStatus", mappedBy="individuals", cascade={"refresh", "remove", "persist"})
     * @joinColumns({
     *   @JoinColumn(name="individuals_id", referencedColumnName="id")
     * })
     */
    private $diagnosers;

  [...]
}

class Diagnosers
{
    /**
     * @var Users
     *
     * @OneToOne(targetEntity="Users", cascade={"persist","remove","detach","merge","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="users_id", referencedColumnName="id", unique=true)
     * })
     */
    private $users;

    /**
     * @var Pros
     *
     * @OneToOne(targetEntity="Pros", cascade={"persist","remove","detach","merge","refresh"})
     * @JoinColumns({
     *   @JoinColumn(name="pros_id", referencedColumnName="id", unique=true)
     * })
     */
    private $pros;

    /**
     * @var Reports
     *
     * @OneToMany(targetEntity="Reports", mappedBy="diagnosers", cascade={"refresh", "remove"})
     */
    private $reports;

    /**
     * @var IndividualsStatus
     *
     * @OneToMany(targetEntity="IndividualsStatus", mappedBy="diagnosers", cascade={"refresh", "remove", "persist"})
     * @joinColumns({
     *   @JoinColumn(name="diagnosers_id", referencedColumnName="id")
     * })
     */
    private $individuals;
}

Note that in individuals, the relation called "Diagnosers" refered to IndividualsStatus entity.
Note that in diagnosers, the relation called "Individuals" refered to IndividualsStatus entity.

When I execute this DQL request:
   $qb->select(array('i', 'iss', 'u')) 
           ->from('IndividualsStatus', 'iss') 
           ->join('iss.individuals', 'i') 
           ->join('i.users', 'u') 
           ->where('iss.diagnosers = ?1') 
           ->andWhere('iss.individuals = ?2') 
           ->setParameters(array(1 => $idDiag, 2 => $id)); 

I retrieve an IndividualsStatus entity:

object(stdClass)[149] 
  public '__CLASS__' => string 'IndividualsStatus' (length=37) 
  public 'individuals' => 
    object(stdClass)[148] 
      public '__CLASS__' => string 'Individuals' (length=31) 
      public 'reference' => string '451' (length=3) 
      public 'maxAdvertisements' => null 
      public 'role' => int 2 
      public 'id' => int 8 
      public 'users' => string 'Users' (length=25) 
      public 'advertisements' => string 'Array(0)' (length=8) 
      public 'diagnosers' => string 'Array(1)' (length=8) 
      public 'ownedReports' => string 'Array(0)' (length=8) 
      public 'reports' => string 'Array(0)' (length=8) 
      public '_em' => null 
  public 'diagnosers' => 
    object(stdClass)[154] 
      public '__CLASS__' => string 'Proxies 
\OpengroupeEntitiesDiagnosersProxy' (length=61) 
      public 'id' => string '19' (length=2) 
  public 'statusIndividuals' => int 1 
  public '_em' => null 

Now i want to access to the "Diagnosers" relation of the Individuals:
\Doctrine\Common\Util\Debug::dump($individualsStatus->getIndividuals()->getDiagnosers());

In my database, this individuals got 2 diagnosers attached, but only 1 is dumped.
For getting the 2, i have to select the Diagnosers relation into my Dql request:

   $qb->select(array('i', 'iss', 'u', 'd')) 
           ->from('IndividualsStatus', 'iss') 
           ->join('iss.individuals', 'i') 
           ->join('i.diagnosers', 'd') 
           ->join('i.users', 'u') 
           ->where('iss.diagnosers = ?1') 
           ->andWhere('iss.individuals = ?2') 
           ->setParameters(array(1 => $idDiag, 2 => $id)); 

Then if i do \Doctrine\Common\Util\Debug::dump($individualsStatus->getIndividuals()->getDiagnosers())
I have my 2 diagnosers display.



 Comments   
Comment by Jonathan Clus [ 27/May/11 ]

I test something more simple with the same entiies:

$diagnosers = $em->getRepository('Diagnosers')->find(19);
$listDiag = $diagnosers->getIndividuals();

In my database, the Diagnoser(19) got 20 individualsStatus(remember the relation called "Individuals" in "Diagnosers" return "IndividualsStatus" entities)
So this function return only 1 individualStatus(minor id in bdd).

I am completly blocked in my developpement. Did my entity annotation for the relation is bad ?

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Formatting

Comment by Benjamin Eberlei [ 05/Jun/11 ]

This issue is related to foreign key identifiers, not using them will solve the problem. Your annotations are good.

However I fixed an issue of this kind some weeks ago. Are you using the Download of 2.1 Beta? Can you try to update to the latest version on Git?

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Yes just seeing i fixed the bug AFTER releasing BEta 1. Please upgrade and verify!

Comment by Benjamin Eberlei [ 11/Jun/11 ]

Resolved





[DDC-1173] Fatal error when a listener resets an object in onFlush and recompute the changeset Created: 26/May/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.5, Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When a listener resets an entity during onFlush and recompute the changeset (setting it to null as there is no changes), the following triggering of preUpdate fails as PreUpdateEventArgs would get null as third argument which is forbidden



 Comments   
Comment by Gediminas Morkevicius [ 30/May/11 ]

Here is a test case:

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;

class DummyListener implements EventSubscriber
{
public function getSubscribedEvents()

{ return array('preUpdate', 'onFlush'); }

public function onFlush(OnFlushEventArgs $args)
{
$uow = $args->getEntityManager()->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $object)

{ $uow->clearEntityChangeSet(spl_object_hash($object)); }

}

public function preUpdate(PreUpdateEventArgs $args)

{ var_dump('invoked'); }

}

triggers fatal error

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Only fixed in 2.1





[DDC-1172] Schema tool does not drop sequences on table drop for PostgreSql platform Created: 26/May/11  Updated: 01/Mar/13  Resolved: 17/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0.5
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Aigars Gedroics Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PostgreSql 8.4


Attachments: File DoctrineDropSequencePatch.diff    

 Description   

When recreating database using

$schemaTool->dropSchema($metaDatas);
$schemaTool->createSchema($metaDatas);

the second line fails with error that the sequence "tbl_id_seq" already exists. It's because the sequence is created without an owner column and schema tool doesn't include "drop sequence" statements in the drop SQL.

I've created a patch which fixes the problem for my environment. Revision numbers in patch is from the local SVN. Doctrine base is 2.0.5.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

That will always drop all sequences also when you only pass some classes in there. We need to find a better solution for this problem.

Comment by Benjamin Eberlei [ 17/Jun/11 ]

Fixed.

Comment by Pierre-Yves LEBECQ [ 01/Mar/13 ]

I don't know if this is the right place to add a comment because this bug is quite old, and if anyone will see it but the code that fixed the reported bug seems to create a bug on my setup. The SchemaTool tries to drop two times the sequences, which produces an error.

The following SQL is generated :

ALTER TABLE utilisateurs DROP CONSTRAINT fk_497b315e7634f637;
ALTER TABLE utilisateurs DROP CONSTRAINT fk_497b315e19863134;
DROP SEQUENCE civilites_civ_id_seq;
DROP SEQUENCE utilisateursClientType_ucty_id_seq;
DROP SEQUENCE utilisateurs_user_id_seq;
DROP SEQUENCE civilites_civ_id_seq;
DROP SEQUENCE utilisateursclienttype_ucty_id_seq;
DROP SEQUENCE utilisateurs_user_id_seq;
DROP TABLE civilites;
DROP TABLE utilisateursClientType;
DROP TABLE utilisateurs

I'm using postgres 9.1.8, Doctrine 2.3.2





[DDC-1168] Implemented tableName -> className and columnName -> fieldName mapping in DatabaseDriver. Created: 24/May/11  Updated: 11/Jun/11  Resolved: 11/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Trivial
Reporter: Alexander Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

As requested a ticket to remind you of looking at this pull request: https://github.com/doctrine/doctrine2/pull/59.

The patch enables custom naming of entities and fieldnames when re-engineering from the database. It can be used when the mapping is done with a script, not by the commandline (yet?).






[DDC-1163] entity persister gets superclasses' metadata for proxied subclass entity Created: 20/May/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.3, 2.0.4, 2.0.5
Fix Version/s: 2.0.6, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Stan Imbt Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

PHP 5.3.6 on Debian Lenny & WinXP, PostgreSQL 8.4 & SQLite 3


Attachments: Zip Archive testcase.zip    

 Description   

Using class table inheritance:

When a proxy for a subclass-entity is registered at the unit of work and another entity, which references that entities' superclass, is added or removed, the employed entity persister gets/uses the superclasses' metadata.

If the change-set of the referenced entity contains fields only defined in the subclass, the persister will create bogus SQL because it has no column names or data types: UPDATE table SET = ? WHERE id = ?

The attached test case is stand-alone, creating an SQLite in-memory DB (sorry, I'm not familiar with your test suite).

Only the path to Doctrine must be adapted at the top of 'run_test.php'.
The file 'SubclassPropertyBugTest.php' also contains a more detailed description.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Verified on 2.0.5, interestingly this bug seems to have vanished in 2.1 / master. I will investigate whats wrong.

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Found the problem and fixed it. Very nasty timing error with inheritance and a false check.





[DDC-1159] From string used as object in QueryBuilder.php Created: 20/May/11  Updated: 25/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Phil Bayfield Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Linux



 Description   

In QueryBuilder.php at line 956, $from is used as an object when it's in fact a string.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Can you show your code leading to this error? Its an object for me.

Comment by Benjamin Eberlei [ 25/Jun/11 ]

Is fixed as part of DDC-1227 and DDC-1221





[DDC-1156] MappedSuperclass not allowed in the middle of an inheritance hierarchy Created: 18/May/11  Updated: 25/Jun/11  Resolved: 25/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.0.4, 2.0.5, 2.1
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Menno Holtkamp Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   

For a Class Table Inheritance mapping configuration, an intermediate MappedSuperclass causes a 'noInheritanceOnMappedSuperClass' mapping exception to be thrown by Doctrine\ORM\Mapping\ClassMetadataFactory::loadMetadata() (line 329). However, the MappedSuperclass only contains some simple properties and no inheritance configuration such as DiscriminatorMap or DiscriminatorColumn settings. The MappedSuperclass DOES extend the upper class in the hierarchy that contains this information using annotations, maybe this way it inherits this inheritance configuration.

The documentation state that a MappedSuperclass can occur in the middle of a inheritance hierarchy.
http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#mapped-superclasses

PS: this mapping seemed to be working fine for me using Doctrine 2.0.4 and Doctrine 2.0.5, further inspection showed that this is not the case. Persistence of an Entity fails, Doctrine wants to update a sequence of the persisted Entity, that does not exist as it is a Class Table Inheritance
PPS: this applies for the 2.1.0-BETA1 release, which is not yet available to create an issue for.



 Comments   
Comment by Benjamin Eberlei [ 05/Jun/11 ]

Fixed, why does this fail on 2.0.4/5? The code doesnt include that exception.

Comment by Menno Holtkamp [ 23/Jun/11 ]

Adding the @MappedSuperclass annotation in the middle of an inheritance hierarchy does not throw an Exception anymore and the Schema Tool generates the proper SQL.

However the problem that was indicated for 2.0.4 and 2.0.5 in the first PS statement of my report remains. It seems that the @SequenceGenerator and in specific the 'sequenceName' setting is ignored for the childs / leafs of the inheritance hierarchy.

Configuration:

Project\Entity\Payment\Method.php
namespace Project\Entity\Payment;
/**
 * @Entity
 * @Table(schema="public", name="payment_method")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discriminator", type="integer")
 * @DiscriminatorMap({
 * "1" = "Project\Entity\Payment\Method\PaymentCard\CreditCard",
 * "2" = "Project\Entity\Payment\Method\PaymentCard\DebitCard",
 * "3" = "Project\Entity\Payment\Method\ElectronicAccount"
 * })
abstract class Method
{
	/**
	 * The Payment Method's identifier
	 *
	 * @var integer
	 * @Column(name="id",type="integer",nullable=false)
	 * @Id
	 * @GeneratedValue(strategy="SEQUENCE")
	 * @SequenceGenerator(sequenceName="payment_method_id_seq")
	 */
	protected $_id;
}
Project\Entity\Payment\Method\PaymentCard.php
namespace Project\Entity\Payment\Method;
/**
 * Project\Entity\Payment\Method\PaymentCard.php
 * Intermediate class that holds common information for PaymentCard Methods
 * No specific database table is required
 *
 * @MappedSuperclass
 */
abstract class PaymentCard extends Method{}

In the Entities that are defined in the discriminator map, we should leave the @Id annotation behind and to use the same sequence as that is used for the Project\Entity\Payment\Method Entity.

Project\Entity\Payment\Method\PaymentCard\CreditCard.php
namespace Project\Entity\Payment\Method\PaymentCard;
/**
 * CreditCard specific class
 *
 * @Entity
 * @Table(schema="public", name="payment_method_payment_card_credit_card")
 */
class CreditCard extends PaymentCard
{

	/**
	 * The Credit Card Payment Method identifier
	 *
	 * Note that no 'Entity-specific' sequence or auto-increment details should be defined, use the inheritance root entity's one
	 * @link http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#class-table-inheritance
	 * @var integer
	 * @Column(name="id",type="integer",nullable=false)
	 * @GeneratedValue(strategy="SEQUENCE")
	 * @SequenceGenerator(sequenceName="payment_method_id_seq")
	 */
	protected $_id;
}

However, Doctrine fails to persist a Project\Entity\Payment\Method\PaymentCard\CreditCard Entity as it tries to increase the value of the sequence of the CreditCard, which does not exist:

failed saving Entity, Project\Entity\Payment, SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "payment_method_payment_card_credit_card_id_seq" does not exist LINE 1: SELECT NEXTVAL('payment_method_payment_card_credit_card_id_s...

When I remove the @MappedSuperclass annotation from the intermediate PaymentCard class, this error does not occur and the proper sequence seems to be used.

Comment by Benjamin Eberlei [ 25/Jun/11 ]

Fixed





[DDC-1148] [Patch] Auto infer parameter type in DQL Created: 11/May/11  Updated: 13/May/11  Resolved: 13/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Minor
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Here is the patch:

http://pastie.org/1891023
http://pastie.org/1891030



 Comments   
Comment by Benjamin Eberlei [ 12/May/11 ]

instanceof DateTimeZone is just wrong. drop that whole branch, TZ only saves the timezone from a DateTime object, infering TYPE::DECIMAL sounds dangerous to me, i would drop that one aswell. The array check has a bug, you call key() and then do nothing with the $key instaed check is_integer on the $value again, which is always an array from the previous check.

Comment by Benjamin Eberlei [ 12/May/11 ]

I thought you wanted to infer the types from the left hand sides of the DQL conditions?

Comment by Guilherme Blanco [ 13/May/11 ]

Implemented: https://github.com/doctrine/doctrine2/commit/8e3fdc5adc0facd4b44f9054ab3681e46131ba8a





[DDC-1147] Allow 0-based InputParameters in DQL Created: 11/May/11  Updated: 11/May/11  Resolved: 11/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently it's impossible to define a 0-based input parameter.
This restriction of Doctrine 2 is odd, because we already have enough support to it, and restriction is merely cosmetic, and also prevents 1:1 array usage on DQL Parameters.



 Comments   
Comment by Guilherme Blanco [ 11/May/11 ]

Implemented in trunk





[DDC-1141] DisconnectedClassMetadataFactory forbids direct XML-to-SQL conversion Created: 10/May/11  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Francois Zaninotto Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Doctrine\ORM\Tools\DisconnectedClassMetadataFactory::newClassMetadataInstance() returns instances of ClassMetadataInfo, while the parent returns instances of ClassMetadata. This creates problems when using SchemaTool to create a schema from an XML mapping for instance:

Fatal error: Call to undefined method Doctrine\ORM\Mapping\ClassMetadataInfo::getQuotedTableName() 
in path/to/Doctrine/ORM/Tools/SchemaTool.php on line 133

This is because schemaTool expects ClassMetadata objects, while it got ClassMetadataInfo objects.

My setup:

 
$config = new Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$driverImpl = new XmlDriver(__DIR__ . '/fixtures');
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$connectionOptions = array(
    'driver' => 'pdo_sqlite',
    'path' => 'database.sqlite'
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);

$metadatas = $cmf->getAllMetadata() // array of ClassMetadataInfo and not ClassMetadata

I think Doctrine\ORM\Tools\DisconnectedClassMetadataFactory::newClassMetadataInstance() should return a ClassMetadata instance.



 Comments   
Comment by Francois Zaninotto [ 10/May/11 ]

Ok, the proposed solution is wrong.

I actually need an array of ClassMetadataInfo and not of ClassMetadata, since the entities don't exist (yet). So the problem lies in the fact that getQuotedTableName() and getQuotedColumnName() are methods of Doctrine\ORM\Mapping\ClassMetadata, and not of Doctrine\ORM\Mapping\ClassMetadataInfo. Moving these two methods up the inheritance path, I managed to create a schema directly from an XML mapping. However, I had to inject the MetadataFactory inside the EM, otherwise the SchemaTool coped when dealing wit hrelationships.

So a working setup to generate SQL from an XML mapping without stepping by Entity generation is:

$config = new Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
$driverImpl = new XmlDriver(__DIR__ . '/fixtures');
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$config->setClassMetadataFactoryName('Doctrine\ORM\Tools\DisconnectedClassMetadataFactory');
$connectionOptions = array(
    'driver' => 'pdo_sqlite',
    'path' => 'database.sqlite'
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
$cmf = $em->getMetadataFactory();

$schemaTool = new SchemaTool($em);
$schemaTool->createSchema($cmf->getAllMetadata());

But again, this requires moving up the two methods from ClassMetadata to ClassMetadataInfo.

Comment by Benjamin Eberlei [ 14/May/11 ]

Moving the methods up is the solution i guess, however i have to think why we did this in the first place, probably because of dependencies.

Comment by Benjamin Eberlei [ 05/Jun/11 ]

This was merged into Doctrine 2.1 / master





[DDC-1133] DuckType AnnotationReader in AnnotationDriver Created: 30/Apr/11  Updated: 30/Apr/11  Resolved: 30/Apr/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: None
Fix Version/s: 2.0.5, 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently the hint is strict in AnnotationDriver for the AnnotationReader. This should be duck-typed to support usage of https://github.com/schmittjoh/annotations



 Comments   
Comment by Benjamin Eberlei [ 30/Apr/11 ]

Implemented





[DDC-1126] SchemaTool fails to dropSchema under SQLite due to ForeignKeyContraints checks Created: 26/Apr/11  Updated: 26/Apr/11  Resolved: 26/Apr/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

When attempting to $schemaTool->dropSchema($metadatas) using SQLite, it fails because it attempts to fetch for foreign key constraints.
Here is the exception:

PHP Fatal error:  Uncaught exception 'Doctrine\DBAL\DBALException' with message 'Operation 'Doctrine\DBAL\Platforms\AbstractPlatform::getListTableForeignKeysSQL' is not supported by platform.' in /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/DBAL/DBALException.php:9
Stack trace:
#0 /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/DBAL/Platforms/AbstractPlatform.php(1839): Doctrine\DBAL\DBALException::notSupported('Doctrine\DBAL\P...')
#1 /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/DBAL/Schema/AbstractSchemaManager.php(261): Doctrine\DBAL\Platforms\AbstractPlatform->getListTableForeignKeysSQL('ProductEntity_P...', NULL)
#2 /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/ORM/Tools/SchemaTool.php(639): Doctrine\DBAL\Schema\AbstractSchemaManager->listTableForeignKeys('ProductEntity_P...')
#3 /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/ORM/Tools/SchemaTool.php(551): Doctrine\ORM\Tools\SchemaTool->getDropSchemaSQL(Array)
#4 /Users/gblanco/Sites/mkx2/core/tests/Tests/Database/AllTests. in /Users/gblanco/Sites/mkx2/core/library/vendors/Doctrine/DBAL/DBALException.php on line 9


 Comments   
Comment by Guilherme Blanco [ 26/Apr/11 ]

Fixed in https://github.com/doctrine/doctrine2/commit/fe66d8bc04de42ab13b83892df11a5ea1533b544





[DDC-1125] Allow return data of Closure on EntityManager::transactional Created: 25/Apr/11  Updated: 25/Apr/11  Resolved: 25/Apr/11

Status: Closed
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Trivial
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently it is impossible to use transactional if you want to return an item from there.

This improvement would allow more flexible behavior from transactional.



 Comments   
Comment by Guilherme Blanco [ 25/Apr/11 ]

Fixed in https://github.com/doctrine/doctrine2/commit/26bd3e381195ba0901c506e8257e0eb6e5d5c931





[DDC-1122] Parsing OR conditions in Where clause throws an exception Created: 22/Apr/11  Updated: 13/May/11  Resolved: 13/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.4
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Oleg Namaka Assignee: Guilherme Blanco
Resolution: Invalid Votes: 1
Labels: None
Environment:

Ubuntu Dedicated Server



 Description   

I have the next query:

        $qb =  $this->_em->createQueryBuilder();
    
          $qb ->select('Inventory')
            ->from('\Entity\Inventory', 'Inventory')
            ->leftJoin('Inventory.Variant', 'Variant')
            ->where('(Variant.isSellable = 0) OR (Variant IS NULL)')
           ->getQuery()->getResult();

that throws an exception:

 PHP Fatal error:  Call to undefined method Doctrine\ORM\Query\AST\ConditionalExpression::isSimpleConditionalExpression() .../Doctrine/ORM/Query/SqlWalker.php on line 1378.

The SqlWalker::walkConditionalPrimary function expects the $primary parameter passed to it to be an instance of Doctrine\ORM\Query\AST\ConditionalPrimary, but it is actually an instance of Doctrine\ORM\Query\AST\ConditionalExpression class that is passed in that case and of course it does not have a method called isSimpleConditionalExpression.

The workaround is to use extra parentheses around the conditions: ((Variant.isSellable = 0) OR (Variant IS NULL)) which does not seem to be very intuitive way.



 Comments   
Comment by Benjamin Eberlei [ 30/Apr/11 ]

Fixed formatting, scheduled for 2.0.5

Comment by Benjamin Eberlei [ 30/Apr/11 ]

It works for me outside the QueryBuilder context when using DQL itself.

Can you call $qb->getQuery()->getDQL() and print that here?

Comment by Guilherme Blanco [ 13/May/11 ]

As stated by this passing unit test:

https://github.com/doctrine/doctrine2/commit/1e9e2de73740667de49847392d978eb4847217a2

This issue is invalid for assigned fix version.





[DDC-1120] AbstractQuery::useResultCache no return type in phpdoc Created: 20/Apr/11  Updated: 01/May/11  Resolved: 01/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0.4
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Trivial
Reporter: Andrey Kolyshkin Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   
  • @param string $resultCacheId
  • @return This query instance.
    */
    public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
    {

must be

  • @param string $resultCacheId
  • @return Doctrine\ORM\AbstractQuery This query instance.
    */
    public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
    {


 Comments   
Comment by Benjamin Eberlei [ 01/May/11 ]

Fixed





[DDC-1110] CTI Entities always trigger ->find even when I'm calling ->getReference Created: 11/Apr/11  Updated: 12/Apr/11  Resolved: 12/Apr/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Guilherme Blanco Assignee: Guilherme Blanco
Resolution: Can't Fix Votes: 0
Labels: None


 Description   

Suppose we have some CTI mapped entities:

Group <- Company

Without having a given Entity on UnitOfWork IdentityMap, if I do:

$groupProxy = $em->getReference('Group', 1);

It will trigger the ->find (accessing the DB). This is correct on this situation, because the Entity can be either Group or Company. But if I do:

$companyProxy = $em->getReference('Company', 1);

There're no sub-classes anymore (Doctrine doesn't know it, but there are other ways to know), so it should correctly return an instance of CompanyProxy instead of trigger the ->find method.

The solution requires to build the hierarchy of Entities using their ClassMetadata. So it is require to loop though all mapped classes on DiscriminatorMap and check if there's 1 class that subclass the given Entity. If positive, return the result of ->find; otherwise a Proxy can be returned.
This is a non-optimal solution (a better solution would be to cache the hierarchy together with ClassMetadata), but it fixes the issue.

Issue could be considered as major since most CTI scenarios trigger unwanted DB queries, but its usage is so restrict that I left as minor.
We should fix that for 2.1 IMHO.



 Comments   
Comment by Benjamin Eberlei [ 12/Apr/11 ]

Actually doctrine knows it, see the check for $metadata->subClasses, which is always on the grabbed entity. So the behavior is alraedy correct, no way to optimize it.

$companyProxy = $em->getReference('Company', 1);

Does:

$cm = $em->getMetadataFor("Company");
if ($cm->subClasses) // 0 for Company




[DDC-1104] Require statement in AnnotationDriver.php can cause PHP Fatal error Created: 06/Apr/11  Updated: 31/Jul/11  Resolved: 31/Jul/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Michael Moravec Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None
Environment:

Linux



 Description   

The require statement in Doctrine/ORM/Mapping/Driver/AnnotationDriver.php causes troubles in some cases. Imagine the situation when you're creating your own class loader which maps all classes and loads all requested classes lazily. When it loads any class from DoctrineAnnotations.php before loading AnnotationDriver and this class is loaded later, you get: PHP Fatal error: Cannot redeclare class ....

Changing require to require_once solves the problem.

Pull request: https://github.com/doctrine/doctrine2/pull/45



 Comments   
Comment by Benjamin Eberlei [ 31/Jul/11 ]

This was fixed for 2.1





[DDC-1094] Add Order and Limit to EntityRepository::findBy() Created: 31/Mar/11  Updated: 01/May/11  Resolved: 01/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently repositories are pretty much useless because you cannot limit/offset or order by columns, which is what repositories are for to implement simple list views. That is why the signatures should be extended to:

findAll(array $orderBy = null, $maxResults = null, $firstResult = null);
findOne(array $criteria, array $orderBy = null, $maxResults = null, $firstResult = null);


 Comments   
Comment by Benjamin Eberlei [ 01/May/11 ]

Implemented, just for findBy() though as findAll() is just a proxy to that in most cases.





[DDC-1080] AbstractHydrator ->_gatherRowData using wrong metadata info Created: 25/Mar/11  Updated: 17/May/11  Resolved: 17/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Van Hauwaert Bert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   

The following worked in a previous version but after upgrading to the latest to fix the security issue, I got an issue.

I will first start with the setup:

MySQL
CREATE TABLE `bar` (
  `barID` int(11) NOT NULL AUTO_INCREMENT,
  `barTitle` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`barID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `foo` (
  `fooID` int(11) NOT NULL AUTO_INCREMENT,
  `fooTitle` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`fooID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE `fooBar` (
  `fooID` int(11) NOT NULL,
  `barID` int(11) NOT NULL,
  `orderNr` int(11) DEFAULT NULL,
  PRIMARY KEY (`fooID`,`barID`),
  KEY `b` (`barID`),
  KEY `f` (`fooID`),
  CONSTRAINT `f` FOREIGN KEY (`fooID`) REFERENCES `foo` (`fooID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `b` FOREIGN KEY (`barID`) REFERENCES `bar` (`barID`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `bar` (barID,barTitle) VALUES (1,'bar title 1');
INSERT INTO `bar` (barID,barTitle) VALUES (2,'bar title 2');
INSERT INTO `bar` (barID,barTitle) VALUES (3,'bar title 3');
INSERT INTO `bar` (barID,barTitle) VALUES (4,'bar title 4');

INSERT INTO `foo` (fooID,fooTitle) VALUES (1,'foo title 1');
INSERT INTO `foo` (fooID,fooTitle) VALUES (2,'foo title 2');

INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,1,0);
INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,2,1);
INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,3,3);
Foo.php
<?php
/**
 * @Entity
 * @Table(name="foo")
 */

class Application_Model_Foo
{
	
	/**
	 * @Id 
	 * @Column(name="fooID", type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	protected $_fooID;
	
	/**
	 * @Column(name="fooTitle", type="string")
	 */
	protected $_fooTitle;
	
	/**
	 * @OneToMany(targetEntity="Application_Model_FooBar", mappedBy="_foo",
	 * cascade={"persist"})
	 * @OrderBy({"_orderNr"="ASC"})
	 */
	protected $_fooBars;

	public function __construct ()
	{
		$this->_fooBars = new \Doctrine\Common\Collections\ArrayCollection();
	}
	
	/**
	 * @return the $fooID
	 */
	public function getFooID ()
	{
		return $this->_fooID;
	}

	/**
	 * @return the $fooTitle
	 */
	public function getFooTitle ()
	{
		return $this->_fooTitle;
	}

	/**
	 * @return the $fooBars
	 */
	public function getFooBars ()
	{
		return $this->_fooBars;
	}

	/**
	 * @param field_type $fooID
	 */
	public function setFooID ($fooID)
	{
		$this->_fooID = $fooID;
	}

	/**
	 * @param field_type $fooTitle
	 */
	public function setFooTitle ($fooTitle)
	{
		$this->_fooTitle = $fooTitle;
	}

	/**
	 * @param field_type $fooBars
	 */
	public function setFooBars ($fooBars)
	{
		$this->_fooBars = $fooBars;
	}


}
Bar.php
<?php
/**
 * @Entity
 * @Table(name="bar")
 */

class Application_Model_Bar
{
	
	/**
	 * @Id 
	 * @Column(name="barID", type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	protected $_barID;
	
	/**
	 * @Column(name="barTitle", type="string")
	 */
	protected $_barTitle;
	
	/**
	 * @OneToMany(targetEntity="Application_Model_FooBar", mappedBy="_bar",
	 * cascade={"persist"})
	 * @OrderBy({"_orderNr"="ASC"})
	 */
	protected $_fooBars;

	public function __construct ()
	{
		$this->_fooBars = new \Doctrine\Common\Collections\ArrayCollection();
	}
	/**
	 * @return the $barID
	 */
	public function getBarID ()
	{
		return $this->_barID;
	}

	/**
	 * @return the $barTitle
	 */
	public function getBarTitle ()
	{
		return $this->_barTitle;
	}

	/**
	 * @return the $fooBars
	 */
	public function getFooBars ()
	{
		return $this->_fooBars;
	}

	/**
	 * @param field_type $barID
	 */
	public function setBarID ($barID)
	{
		$this->_barID = $barID;
	}

	/**
	 * @param field_type $barTitle
	 */
	public function setBarTitle ($barTitle)
	{
		$this->_barTitle = $barTitle;
	}

	/**
	 * @param field_type $fooBars
	 */
	public function setFooBars ($fooBars)
	{
		$this->_fooBars = $fooBars;
	}


}
FooBar.php
<?php
/**
 * @Table(name="fooBar")
 * @Entity
 */
class Application_Model_FooBar
{

	/**
	 * @ManyToOne(targetEntity="Application_Model_Foo")
	 * @JoinColumn(name="fooID", referencedColumnName="fooID")
	 * @Id
	 */
	protected $_foo = null;

	/**
	 * @ManyToOne(targetEntity="Application_Model_Bar")
	 * @JoinColumn(name="barID", referencedColumnName="barID")
	 * @Id
	 */
	protected $_bar = null;

	/**
	 * @var integer orderNr
	 * @Column(name="orderNr", type="integer", nullable=false)
	 */
	protected $_orderNr = null;

	/**
	 * Retrieve the foo property
	 *
	 * @return Application_Model_Foo
	 */
	public function getFoo()
	{
		return $this->_foo;
	}

	/**
	 * Set the foo property
	 *
	 * @param Application_Model_Foo $foo
	 * @return Application_Model_FooBar
	 */
	public function setFoo($foo)
	{
		$this->_foo = $foo;
		return $this;
	}

	/**
	 * Retrieve the bar property
	 *
	 * @return Application_Model_Bar
	 */
	public function getBar()
	{
		return $this->_bar;
	}

	/**
	 * Set the bar property
	 *
	 * @param Application_Model_Bar $bar
	 * @return Application_Model_FooBar
	 */
	public function setBar($bar)
	{
		$this->_bar = $bar;
		return $this;
	}

	/**
	 * Retrieve the orderNr property
	 *
	 * @return integer|null
	 */
	public function getOrderNr()
	{
		return $this->_orderNr;
	}

	/**
	 * Set the orderNr property
	 *
	 * @param integer|null $orderNr
	 * @return Application_Model_FooBar
	 */
	public function setOrderNr($orderNr)
	{
		$this->_orderNr = $orderNr;
		return $this;
	}


}

When I execute the following code

IndexController.php
$foo = $this->_em->find('Application_Model_Foo', 1);
$fooBars = $foo->getFooBars();
var_dump(count($fooBars));

I expect "3" as output. But I get "1".

There seems to be an issue with the metadata or the used fieldname in the _gatherRowData in the AbstractHydrator.

The following is a dump of $classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$cache[$key]['dqlAlias']]);

abstractHydrator
Doctrine\ORM\Mapping\ClassMetadata Object
(
    [reflFields] => Array
        (
            [_orderNr] => ReflectionProperty Object
                (
                    [name] => _orderNr
                    [class] => Application_Model_FooBar
                )

            [_foo] => ReflectionProperty Object
                (
                    [name] => _foo
                    [class] => Application_Model_FooBar
                )

            [_bar] => ReflectionProperty Object
                (
                    [name] => _bar
                    [class] => Application_Model_FooBar
                )

        )

    [_prototype:Doctrine\ORM\Mapping\ClassMetadata:private] => 
    [name] => Application_Model_FooBar
    [namespace] => 
    [rootEntityName] => Application_Model_FooBar
    [customRepositoryClassName] => 
    [isMappedSuperclass] => 
    [parentClasses] => Array
        (
        )

    [subClasses] => Array
        (
        )

    [namedQueries] => Array
        (
        )

    [identifier] => Array
        (
            [0] => _foo
            [1] => _bar
        )

    [inheritanceType] => 1
    [generatorType] => 5
    [fieldMappings] => Array
        (
            [_orderNr] => Array
                (
                    [fieldName] => _orderNr
                    [type] => integer
                    [length] => 
                    [precision] => 0
                    [scale] => 0
                    [nullable] => 
                    [unique] => 
                    [columnName] => orderNr
                )

        )

    [fieldNames] => Array
        (
            [orderNr] => _orderNr
        )

    [columnNames] => Array
        (
            [_orderNr] => orderNr
        )

    [discriminatorValue] => 
    [discriminatorMap] => Array
        (
        )

    [discriminatorColumn] => 
    [table] => Array
        (
            [name] => fooBar
        )

    [lifecycleCallbacks] => Array
        (
        )

    [associationMappings] => Array
        (
            [_foo] => Array
                (
                    [fieldName] => _foo
                    [id] => 1
                    [joinColumns] => Array
                        (
                            [0] => Array
                                (
                                    [name] => fooID
                                    [referencedColumnName] => fooID
                                    [unique] => 
                                    [nullable] => 1
                                    [onDelete] => 
                                    [onUpdate] => 
                                    [columnDefinition] => 
                                )

                        )

                    [cascade] => Array
                        (
                        )

                    [inversedBy] => 
                    [targetEntity] => Application_Model_Foo
                    [fetch] => 2
                    [type] => 2
                    [mappedBy] => 
                    [isOwningSide] => 1
                    [sourceEntity] => Application_Model_FooBar
                    [isCascadeRemove] => 
                    [isCascadePersist] => 
                    [isCascadeRefresh] => 
                    [isCascadeMerge] => 
                    [isCascadeDetach] => 
                    [sourceToTargetKeyColumns] => Array
                        (
                            [fooID] => fooID
                        )

                    [joinColumnFieldNames] => Array
                        (
                            [fooID] => fooID
                        )

                    [targetToSourceKeyColumns] => Array
                        (
                            [fooID] => fooID
                        )

                    [orphanRemoval] => 
                )

            [_bar] => Array
                (
                    [fieldName] => _bar
                    [id] => 1
                    [joinColumns] => Array
                        (
                            [0] => Array
                                (
                                    [name] => barID
                                    [referencedColumnName] => barID
                                    [unique] => 
                                    [nullable] => 1
                                    [onDelete] => 
                                    [onUpdate] => 
                                    [columnDefinition] => 
                                )

                        )

                    [cascade] => Array
                        (
                        )

                    [inversedBy] => 
                    [targetEntity] => Application_Model_Bar
                    [fetch] => 2
                    [type] => 2
                    [mappedBy] => 
                    [isOwningSide] => 1
                    [sourceEntity] => Application_Model_FooBar
                    [isCascadeRemove] => 
                    [isCascadePersist] => 
                    [isCascadeRefresh] => 
                    [isCascadeMerge] => 
                    [isCascadeDetach] => 
                    [sourceToTargetKeyColumns] => Array
                        (
                            [barID] => barID
                        )

                    [joinColumnFieldNames] => Array
                        (
                            [barID] => barID
                        )

                    [targetToSourceKeyColumns] => Array
                        (
                            [barID] => barID
                        )

                    [orphanRemoval] => 
                )

        )

    [isIdentifierComposite] => 1
    [containsForeignIdentifier] => 1
    [idGenerator] => Doctrine\ORM\Id\AssignedGenerator Object
        (
        )

    [sequenceGeneratorDefinition] => 
    [tableGeneratorDefinition] => 
    [changeTrackingPolicy] => 1
    [isVersioned] => 
    [versionField] => 
    [reflClass] => ReflectionClass Object
        (
            [name] => Application_Model_FooBar
        )

)

$fieldName = $this->_rsm->metaMappings[$key]; is "fooID" or "barID"

After assigning $cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName); you get false back.

So you check for fooID / barID in the array

[identifier] => Array
        (
            [0] => _foo
            [1] => _bar
        )

what of course is false because they aren't in the array.

When I set the flag $cache[$key]['isIdentifier'] to true for the 2 fields, I get an output of 3 as expected.

So the fieldname is wrong or the identifier list is wrong.



 Comments   
Comment by Benjamin Eberlei [ 27/Mar/11 ]

"In a previous version"? What exact version please? I can't pin down the commits with such a broad statement.

Edit: Ah you are working with master and fk+pk support. Can you still find out the version? There were some general fixes in the hydrator and one larger refactoring since I merged the fk+pk branch.

Comment by Van Hauwaert Bert [ 29/Mar/11 ]

This is the last log on a server where it is still working:
ORM:

commit 180078d0f6fa97bf5f3398e8c5d2f56030236c33
Author: Guilherme Blanco <guilhermeblanco@gmail.com>
Date:   Mon Mar 14 01:04:50 2011 -0300

    Added namedQueries as optional during serialization of ClassMetadata.

Common:

commit ba63ae0f0b6b62a2a8617f01386698730ff2b713
Author: Jonathan H. Wage <jonwage@gmail.com>
Date:   Wed Feb 16 10:17:48 2011 -0600

    Revert "Adding Driver interface for mapping drivers."

DBAL:

commit ae084d9c6975356f8f0f10d8802abe91df45b739
Author: Benjamin Eberlei <kontakt@beberlei.de>
Date:   Sun Jan 30 10:58:14 2011 -0500

    Release {$version}
Comment by Benjamin Eberlei [ 29/Mar/11 ]

Ah i know what the problem might be.

Comment by Van Hauwaert Bert [ 01/Apr/11 ]

Great! Looking forward for a fix. It would solve a lot of issues I'm having now.

Comment by Benjamin Eberlei [ 14/May/11 ]

The bug appears because you rename the id column from the default value. If you rename the property to $fooId instead of $_fooId it works.

I have to check how i can fix this issue, but its complicated.

Comment by Benjamin Eberlei [ 14/May/11 ]

There are two potential fixes for this bug, both have their drawbacks, we have to discuss them in the team. For now rename the field to the name of the column to get it working.

Comment by Benjamin Eberlei [ 14/May/11 ]

Not a blocker, there is a workaround

Comment by Benjamin Eberlei [ 17/May/11 ]

Fixed





Several features to batch eager selects more efficently (DDC-952)

[DDC-1060] Use Hydrators inside Persisters Created: 06/Mar/11  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

The hydration code should be moved out of the persisters and re-using the Hydrators.

Reasons:

  • No duplication of hydration code necessary anymore.
  • More complex hydration (eager loads) possible inside persister

Implementation:

  • Either use a SimpleObjectHydrator or reuse the ObjectHydrator (benchmark)

Check for performance first.



 Comments   
Comment by Benjamin Eberlei [ 06/Mar/11 ]

A first milestone of this is done: https://github.com/doctrine/doctrine2/commit/851f44a066ffbe7849c1402d5e192be9bbd4383e

Comment by Benjamin Eberlei [ 16/Mar/11 ]

Merged





[DDC-1059] Add helper for ResultSetMapping Created: 05/Mar/11  Updated: 15/May/11  Resolved: 15/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None


 Description   

Building a ResultSetMapping yourself is tedious work, it can be simplified by passing ClassMetadata instances, so that the RSM even changes when the Entity Metadata changes.

Two use-cases:

1. Add Entity X as Root Entity
2. Add Entity X as Fetch Joined Entity of parent entity Y



 Comments   
Comment by Michael Ridgway [ 24/Mar/11 ]

What are the inputs and outputs from this? Would this return just the ResultSetMap and then you'd be expected to generate the SQL yourself?

The main reason for using the RSM is if you are trying to do something that is not supported in DQL. With the SQL query building functions being added to the DBAL, would it be better to have a helper that takes in DQL (or DQL parts?) and returns the SQL query and the RSM?

I'm not sure if this covers all use cases, but probably the most common.

Comment by Benjamin Eberlei [ 25/Mar/11 ]

I was thinking this accepts a ClassMetadata instance, or the EM + ClassName. Additionally you might need to pass a prefix when you have to build a query for many tables that have equally named columns:

$rsm->addEntityColumnsFromClassMetadata($em->getClassMetadata('Article'));
$rsm->addEntityColumnsFromClassMetadata($em->getClassMetadata('Category'), 'category_');
// SELECT a.*, c.category_id, c.category_name, c.category_desc FROM Article a INNER JOIN Category c

Naming and API is open to discussion obviously

The goal should be that you dont have to change your native queries when you add or remove a column from your entity.

Comment by Michael Ridgway [ 29/Mar/11 ]

I made a first pass at this: https://github.com/mridgway/doctrine2/commit/20dc72ef9ae0d7c4afead35c249c224b95570aa7

This basically creates new functions with the same functionality as addEntityResult and addJoinedEntityResult except that they take in ClassMetadata and will add the fields from the class automatically. There is also an additional parameter for each function that is a prefix that is added to the entity's column name (see test case for example).

One problem with this implementation is that it doesn't use DBAL\Platforms\AbstractPlatform::getSQLResultCasing since we don't have access to the connection.

There are probably other problems, but I wanted to get some feedback on whether this is heading in the right direction.

Comment by Benjamin Eberlei [ 15/May/11 ]

This was implemented by Michael, thank you!





[DDC-1056] Using the StaticPHPDriver throws PHP Error Undefined property: Doctrine\ORM\Mapping\Driver\StaticPHPDriver::$_classNames Created: 03/Mar/11  Updated: 04/Mar/11  Resolved: 04/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: Git Master
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Trivial
Reporter: Steven Rosato Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: Text File 0001-DDC-1056-PHPStaticDriver-was-missing-two-instance-va.patch    

 Description   

Using the StaticPHPDriver throws PHP Error Undefined property: Doctrine\ORM\Mapping\Driver\StaticPHPDriver::$_classNames

this is due to the class not having the two required instance variables $this->_classNames and $this->_fileExtension.



 Comments   
Comment by Steven Rosato [ 03/Mar/11 ]

I have attached the patch that resolves the issue.

Comment by Steven Rosato [ 03/Mar/11 ]

I applied the patch and added a pull request. https://github.com/doctrine/doctrine2/pull/34

Comment by Benjamin Eberlei [ 04/Mar/11 ]

Fixed





[DDC-1043] Unit of Work - computeChangeSet Created: 25/Feb/11  Updated: 01/May/11  Resolved: 01/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: victor Velkov Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In the unit of work in the compute Change Set function. When comparing the old and the new value of a field. In the case 'Entity is "fully" MANAGED'. And the values are strings it is used

$orgValue != $actualValue

comparison operator instead of

$orgValue !== $actualValue

Which lead to not detecting some changes. I know it is not something major, but it is really annoying. So please fix it for the next release.

Thanks in advance.



 Comments   
Comment by Benjamin Eberlei [ 25/Feb/11 ]

Can you give an example? The ones with null are already catched with the second part, so i cannot think of others.

($orgValue === null ^ $actualValue === null)
Comment by victor Velkov [ 26/Feb/11 ]

well in my case I want to save a field with country code with lets say something like '+44'. But then i want to change it to just '44' it doesn't catch the difference and the column in the DB is varchar and in the entity it is set as string so it must use the strict comparison operator.

Comment by Benjamin Eberlei [ 26/Feb/11 ]

What the fuck, i didn't know PHP had THIS strange conversion rules. The problem with using === is that for integer columns for example "44" vs 44 would determine a change and I cannot check for "string" column yes no at that point because this bit of code is very important for performance of UnitOfWork::commit().

Can we come up with a universal condition that detects this string change and keeps the comparison of all others equal?

Comment by victor Velkov [ 27/Feb/11 ]

To be honest I didn't know about the int problem I will think on it if I can find a solution I will tell you straight away.

Comment by victor Velkov [ 02/Mar/11 ]

Well the best that i could come up with is

                else if((is_string($orgValue) && $orgValue !== $actualValue)
                			|| ($orgValue === null ^ $actualValue === null)) {
					$changeSet[$propName] = array($orgValue, $actualValue);
                } else if ((!is_string($orgValue) && $orgValue != $actualValue)
                			|| ($orgValue === null ^ $actualValue === null)) {
                    $changeSet[$propName] = array($orgValue, $actualValue);
                }

Logically depending on the type of the old value to decide which operator to use as the old value was type cast by the DBAL Type class so we can depend on it.

Comment by Benjamin Eberlei [ 04/Apr/11 ]

Maybe we really have to change this:

diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 682e906..8f68c3e 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -467,9 +467,7 @@ class UnitOfWork implements PropertyChangedListener
                     }
                 } else if ($isChangeTrackingNotify) {
                     continue;
-                } else if (is_object($orgValue) && $orgValue !== $actualValue) {
-                    $changeSet[$propName] = array($orgValue, $actualValue);
-                } else if ($orgValue != $actualValue || ($orgValue === null ^ $actualValue === null)) {
+                } else if ($orgValue !== $actualValue) {
                     $changeSet[$propName] = array($orgValue, $actualValue);
                 }
             }

Rather have more changes, which would be the developers need to take care of then ignoring these tricky casting issues.

Comment by Benjamin Eberlei [ 01/May/11 ]

Fixed, but only merged into 2.1 / master so people can test this more.





[DDC-1041] UnitOfWork tryGetById method is always called with the rootEntityName Created: 24/Feb/11  Updated: 04/Mar/11  Resolved: 04/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Couragier Sébastien Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

LAMP



 Description   

My problem : i have a class table inheritance, with only 3 class, one abstract and two concrete.
says AbstractClass, ConcretClassA and ConcreteClassB
All three are declared with @entity

if i already have in my identity map the ConcretClassA with id = 1
when i do an entityManager->find('ConcreteClassB', 1) the identityMap returns me the ConcretClassA with id = 1
that's not correct !
it should return a null value instead

That's because the entityRepository (and all the other doctrine class) call the UnitOfWork tryGetById with the rootEntityName, which in my case is AbstractClass.
See the first line of the entityRepository's find method :

$this->_em->getUnitOfWork()->tryGetById($id, $this->_class->rootEntityName)

if i change this line to :

$this->_em->getUnitOfWork()->tryGetById($id, $this->_class->name)

the find method return the expected null value.

So, why the UnitOfWork tryGetById method is always called with the rootEntityName ?



 Comments   
Comment by Benjamin Eberlei [ 25/Feb/11 ]

The identity map HAS to work by root entity name.

Otherwise think of an inheritance hierachy A > B. Then both $em>find('A', 1); and $em->find('B', 1); should return the same instance.

If this does not hold you are screwed.

Your problem is more subtle, i am not sure what the expected behavior should be here.

Comment by Couragier Sébastien [ 28/Feb/11 ]

In my sense, the client code should exactly knows the inheritance hierachy, and exactly know what it wants too, so if it asks for an 'A' instance, you can't return a 'B' instance, although A inherit from B.

Comment by Benjamin Eberlei [ 28/Feb/11 ]

I agree with you except for the last sentence part.

If A->B and you query for B with Id 1 it should treturn an A if it exists. But if B->C and A->C then find(A) should only ever return As or Cs never, Bs.

Comment by Couragier Sébastien [ 28/Feb/11 ]

I agree.
Perhaps my problem is more specific to the class table inheritance strategy with an abstract class at the top of it.
Here's my identityMap's dump (with my first comment inheritance example) at the time the problem occurs :

'AbstractClass' =>
array
1 => string 'ConcretClassA'
2 => string 'ConcretClassA'
3 => string 'ConcretClassA'
367 => string 'ConcretClassB'
368 => string 'ConcretClassB'
369 => string 'ConcretClassB'

And, at this time, in my code, i would like to know if the id 1 is a ConcretClassB. If the id 1 is a ConcretClassA, i must throw an exception.
So, how could i test if the id 1 is a ConcretClassB or not, if the find('ConcretClassB', 1) method returns me the ConcretClassA 1 ?

thx for your help

Comment by Benjamin Eberlei [ 28/Feb/11 ]

Cant you just check instanceof?

$a = $em->find('ConcretClassA', $aId);
if ($a instanceof ConcretClassB) {
   throw new Exception();
}
Comment by Couragier Sébastien [ 28/Feb/11 ]

Of course i can.
But i thought Doctrine should already have to do this check internally for us. Because we must now be very careful with the find method's returns...

Nevermind, i don't have all the uses case Doctrine have to handle with inheritance in mind; so if you say it is to the client code to check, and it is a completely normal behavior, then it's okay for me.

Comment by Benjamin Eberlei [ 28/Feb/11 ]

i will change this behavior in the future, i am just making suggestions for you to fix it now. Using instanceof will also be forwards compatible since "null instanceof Class" is always false.

In any case the level of having to be careful is the same, using null instead of an object can get you into troubles aswell.

Comment by Couragier Sébastien [ 03/Mar/11 ]

Perhaps throw a \Doctrine\ORM\EntityNotFoundException would be a better option than return a null value ?

Comment by Benjamin Eberlei [ 04/Mar/11 ]

Fixed.





[DDC-1036] the Aggregate Expressions "AVG" | "MAX" | "MIN" | "SUM", should be followed by SimpleArithmeticExpression Created: 16/Feb/11  Updated: 20/Feb/11  Resolved: 20/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: None
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Jison Xiao Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

the Aggregate Expressions "AVG" | "MAX" | "MIN" | "SUM", should be not only followed by StateFieldPathExpression , but also SimpleArithmeticExpression,
see http://www.doctrine-project.org/docs/orm/2.0/en/reference/dql-doctrine-query-language.html#aggregate-expressions

i found it can not execute dql like
select sum(c.quantity * c.price) total_price from cart c

i think, this should be a bug



 Comments   
Comment by Guilherme Blanco [ 19/Feb/11 ]

You are totally right.

I fixed on trunk repository. Thanks a lot for pointing out this issue. =)

Comment by Benjamin Eberlei [ 20/Feb/11 ]

Merged into 2.0.x also





[DDC-1034] Registered lifecycle callbacks of derived classes have unexpected call sequence Created: 15/Feb/11  Updated: 04/Mar/11  Resolved: 04/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Bart Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File TestClasses.php    

 Description   

Situation:
Create an abstract base class (@InheritanceType("JOINED")) and a derived class, both having the annotation @HasLifecycleCallbacks and both having a method with annotation @PostLoad (different method names). The sequence of methods being called when an object is loaded from the database is not as expected.

Expected output:
Called Che\Tmp\BaseClass::PostLoadBase
Called Che\Tmp\DerivedClass::PostLoadDerived
(base value, derived value)

Actual output:
Called Che\Tmp\BaseClass::PostLoadBase
Called Che\Tmp\DerivedClass::PostLoadDerived
Called Che\Tmp\BaseClass::PostLoadBase
(base value)

Test code:
See attachment for classes

// Assume there is an entity manager $em
// Create object
$newDerived = new \Che\Tmp\DerivedClass();
$em->persist($newDerived);

// Fetch object
$derived = $em->findById('\Che\Tmp\DerivedClass', 1);
$derived->echoList();

Possible problem cause

ClassMetadataInfo::addLifecycleCallback($callback, $event) method has a note 'If the same callback is registered more than once, the old one will be overridden'. We are not sure whether this is the case.



 Comments   
Comment by Benjamin Eberlei [ 04/Mar/11 ]

Fixed.





[DDC-1029] renaming "load()" in proxy to "__load()" Created: 11/Feb/11  Updated: 13/May/11  Resolved: 13/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Jonathan H. Wage Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Reference
relates to MODM-118 rename "load" method in Proxy object ... Resolved

 Description   

It would be really great if the method "load" is renamed to something more protected like "__load" or "_doctrineOdmLoad" like it has done for public properties
public $__dm;
public $__identifier;
public $isInitialized = false;
Because otherwise if a referenced document has the same method "load" it causes error like this

"Fatal error: Cannot redeclare Proxies\ProjectProxy::load() in /projects/tbi_doctrine/tmp/doctrine/proxies/ProjectProxy.php on line 46"



 Comments   
Comment by Jonathan H. Wage [ 11/Feb/11 ]

This issue is a duplicate of another issue in the ODM. The fix applies to the ORM as well.

Comment by Guilherme Blanco [ 13/May/11 ]

Fixed on master

https://github.com/doctrine/doctrine2/commit/e5381286458ac467543b23ac1a1a1c613bbc2ff1





[DDC-1025] Please repalce 'Doctrine\XXX\YYY' with '\Doctrine\XXX\YYY' in code and document Created: 09/Feb/11  Updated: 01/Apr/14  Resolved: 01/Apr/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Documentation, DQL, Mapping Drivers, ORM, Tools
Affects Version/s: 2.0.1
Fix Version/s: 2.1, 2.2
Security Level: All

Type: Improvement Priority: Major
Reporter: ben yan Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 7
Labels: None


 Description   

It will help us use the namespace and code autocomplete in some IDE.



 Comments   
Comment by Matthieu Napoli [ 08/Apr/11 ]

Hi, do you have any more information about this ?

I'm confused because the php documentation uses the Doctrine\XXX way, and everywhere I've seen, it is used like that.

Thanks

Comment by Karsten Dambekalns [ 11/Apr/11 ]

The issue is simple and logical.

When an IDE (I am using PhpStorm and it does it like this) sees a namespace in a file, upon seeing namespaces afterwards, it sees them as absolute if they have a leading backslash, or relative when it does not. This affects the resolution of classes for type navigation, code inspection, ... The same rules as for actual PHP code should be used within comments.

Here is an example:

namespace Foo;

class Bar {

  /**
   * @var Baz
   */
  protected $baz;

  /**
   * @var \Quux
   */
  protected $quux;

}

The IDE will think $baz is \Foo\Baz and $quux will be seen as being \Quux. Now if you have some reference to Doctrine here, and it was relative, the IDE would assume it's \Foo\Doctrine\...

Comment by Benjamin Eberlei [ 11/Apr/11 ]

Well yes, but since all our code examples have no leading namespace argument this means the code is in the default namespace, making Doctrine\XXX\YY a relative namespace that is actually valid.

Comment by Karsten Dambekalns [ 11/Apr/11 ]

Yes, but the source code docblocks are what is meant here as far as I am concerned.

Comment by Andrey Kolyshkin [ 13/May/11 ]

Example (Entitymanager.php):

namespace Doctrine\ORM;

and

/**
  * The used Configuration.
  *
  * @var Doctrine\ORM\Configuration
  */
   private $config;

Result:
Doctrine\ORM\Doctrine\ORM\Configuration

Should be:

/**
  * The used Configuration.
  *
  * @var Configuration
  */
   private $config;

Or

/**
  * The used Configuration.
  *
  * @var \Doctrine\ORM\Configuration
  */
   private $config;
Comment by Miha Vrhovnik [ 27/May/11 ]

Why don't you take this to the PhpStorm tracker as it surely is a bug in IDE?

Comment by Karsten Dambekalns [ 27/May/11 ]

Miha, what makes you think it's an IDE bug? In a class in namespace Foo another class named Bar is \Foo\Bar, but \Bar is \Bar. Why is it a bug if the IDE follows the namespace resolution rules?

Comment by Michael Ridgway [ 11/Jul/11 ]

The issue is that PHPStorm and NetBeans have different class resolution rules. I also use PHPStorm and most of Doctrine does not resolve auto-completion correctly because of this issue.

I'd be willing to work on this if it would be accepted.

Comment by Andrew Mackrodt [ 29/Sep/11 ]

I've been evaluating PhpStorm and also came across this issue; I believe the problem is due to Doctrine rather than being a bug with the IDE although it would be nice if PhpStorm would assume namespaces are absolute if they're not resolved upon an initial lookup.

I created a quick c# app to append the beginning forward slash to any @var or @return attributes within Doctrine's source. It's working for me with Doctrine 2.1.2 and PhpStorm (IntelliJ): http://pastebin.com/4HxiWvJA - hopefully this will be of use for anyone else using these IDEs;. Note: the application doesn't detect multiple line annotations although the only one I'm aware of is the getAST method in Doctrine\ORM\Query.php.

Comment by Benjamin Eberlei [ 13/Dec/11 ]

This issue is referenced in Github Pull-Request GH-215
https://github.com/doctrine/doctrine2/pull/215

Comment by Benjamin Eberlei [ 13/Dec/11 ]

This issue is referenced in Github Pull-Request GH-216
https://github.com/doctrine/doctrine2/pull/216

Comment by Steve Müller [ 01/Apr/14 ]

Fixed in commits:
https://github.com/doctrine/doctrine2/commit/3b259dcb42e8ba332231846401d8d97296f3dd65
https://github.com/doctrine/doctrine2/commit/bda98150c4e876f0b1b89d757c864a70ad7c583a





[DDC-1024] the EntityGenerator generate getters and setters for properties of the parent class Created: 09/Feb/11  Updated: 04/Jan/12  Resolved: 12/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: Git Master
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Christophe Coevoet Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

when using the EntityGenerator to generate getters and setters of two classes mapped with annotations, one inheriting from the other, the EntityGenerator generates getters and setters for the properties of the parent class in the child class too. This occurs since the recent EntityGenerator changes (as it did not care about inheritance before).
I suppose this is due to the fact that the getters and setters of the parent class are not yet generated when handling the child class.

I haven't try if it works well when using XML or YAML for the mapping.



 Comments   
Comment by Benjamin Eberlei [ 12/Feb/11 ]

How do you define inheritance?

Comment by Christophe Coevoet [ 12/Feb/11 ]

In my case, it was inheritance using a Single Table Inheritance.

Both entities were in the same Symfony2 Bundle so the getters and setters were generated by the same command.

Comment by Benjamin Eberlei [ 12/Feb/11 ]

fixed

Comment by yakobe [ 01/Nov/11 ]

I am still having this problem with the 2.1 branch. Should it not happen anymore?

Comment by Albert Brand [ 04/Jan/12 ]

I'm also still seeing this in 2.1 (bundled with Symfony2).
Using single table inheritance, adding a protected or public property to the abstract class causes private properties & getters & setters to be added to all subclasses.





[DDC-1018] INDEX BY does not work in JOIN clauses Created: 04/Feb/11  Updated: 05/Feb/11  Resolved: 05/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0.1
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Dependency
is required for DDC-250 ArrayCollection Key Column @indexBy Resolved

 Description   

It seems INDEX BY only works in the FROM, not in JOIN clauses.

This is a dependency for DDC-250



 Comments   
Comment by Benjamin Eberlei [ 05/Feb/11 ]

Fixed





[DDC-1017] mysql error when renaming a manyToOne property Created: 04/Feb/11  Updated: 19/Jun/11  Resolved: 19/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Pim Hazebroek Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 3
Labels: None
Environment:

Ubuntu Maverick 10.10
PHP 5.3.3
System Linux pim-laptop 2.6.35-25-generic-pae #44-Ubuntu SMP Fri Jan 21 19:01:46 UTC 2011 i686
mysql Ver 14.14 Distrib 5.1.49, for debian-linux-gnu (i686) using readline 6.1


Attachments: File export.sql     File Task.php     File User.php    

 Description   

These are my initial properties with annotations:

// Task.php
/**

  • @ManyToOne(targetEntity="Maia\Model\User", inversedBy="tasks")
    */
    protected $user;

// User.php
/**

  • @OneToMany(targetEntity="Maia\Model\Task", mappedBy="user")
    */
    protected $tasks;

At this stage, everythings works fine.

However when I try to rename the property $user to $author like so:

// User.php
/**

  • @OneToMany(targetEntity="Maia\Model\Task", mappedBy="author")
    */
    protected $tasks;

and change the corresponding entity like this:
/**

  • @ManyToOne(targetEntity="Maia\Model\User", inversedBy="tasks")
    */
    protected $author;

and then try to update my database using the './doctrine orm:schema-tool:update --force' command, I get the following error:
[PDOException]
SQLSTATE[HY000]: General error: 1025 Error on rename of './maia/#sql-508_2be' to './maia/Task' (errno: 150)

in the database 'information_schema' and then tabel 'key_column_usage' I find this line:
CONSTRAINT_CATALOG Null
CONSTRAINT_SCHEMA maia
CONSTRAINT_NAME Task_ibfk_1
TABLE_CATALOG Null
TABLE_SCHEMA maia
TABLE_NAME Task
COLUMN_NAME user_id
ORDINAL_POSITION 1
POSITION_IN_UNIQUE_CONSTRAINT 1
REFERENCED_TABLE_SCHEMA maia
REFERENCED_TABLE_NAME User
REFERENCED_COLUMN_NAME id

I had to perform the following query on my database before I was able to update:
ALTER TABLE User DROP FOREIGN KEY Task_ibfk_1;

Maybe I am doing something wrong, this is my first project with Doctrine, but I tweeted about the error and somebody asked me to create a ticket so here it is.



 Comments   
Comment by Benjamin Eberlei [ 19/Jun/11 ]

Fixed





[DDC-1014] Evaluate common date related functions for DQL inclusion Created: 02/Feb/11  Updated: 27/Mar/11  Resolved: 27/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

To check:

  • Difference in days between two dates
  • Add/subtract an interval to a date
  • Format a date
  • Return only Year, Month or Day, Day of Week, Week of Year of the date


 Comments   
Comment by Benjamin Eberlei [ 27/Mar/11 ]

MySQL: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

DATEDIFF, DATE_ADD, DATE_SUB, DATE_FORMAT, YEAR, MONTH, DAY, WEEK, DATE

Postgres: http://developer.postgresql.org/pgdocs/postgres/functions-datetime.html

DATEDIFF, DATE_ADD/SUB (Operator), Kein Format?, YEAR, MONTH, DAY, WEEK

Sqlite: http://www.sqlite.org/lang_datefunc.html

Operators, date(), format, YEAR, MONTH, DAY, WEEK,DATE

Oracle: http://www.oracle-dba-online.com/sql/date_operators_functions.htm http://www.akadia.com/services/ora_date_time.html

Operators, TO_CHAR()/EXTRACT()

MSSQL: http://msdn.microsoft.com/en-us/library/aa258863%28v=sql.80%29.aspx

Comment by Benjamin Eberlei [ 27/Mar/11 ]

Implemented





[DDC-1012] Add isNull($param) and isNotNull($param) to querybuilder Created: 02/Feb/11  Updated: 22/Apr/11  Resolved: 20/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0, 2.0.1, Git Master
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

Add isNull($param) and isNotNull($param) to querybuilder



 Comments   
Comment by Guilherme Blanco [ 19/Feb/11 ]

Added to trunk. =)

Comment by Marijn Huizendveld [ 22/Apr/11 ]

I'm sorry but this is not working for me on 2.0.3. I've been looking at the source code to find a reference of it but it seems to be removed altogether?!





[DDC-1008] Entity Generator Stub Method For Id Generator Created: 31/Jan/11  Updated: 02/Feb/11  Resolved: 02/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0.1
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Stephen Walker Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In the EntityGenerator when the id setting has a generator of NONE it does not add the stub method for setting the id keys value, here's my fix:

around line 478 in the _generateEntityStubMethods function, the first foreach which checks for the id mapping, change:

if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id']) {

TO

if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id'] || ($this->_getIdGeneratorTypeString($metadata->generatorType) == 'NONE')) {



 Comments   
Comment by Benjamin Eberlei [ 02/Feb/11 ]

Fixed





[DDC-1006] Entity Generator Regenerate If Not New Created: 31/Jan/11  Updated: 02/Feb/11  Resolved: 02/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0.1
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Stephen Walker Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When regenerating entities from xml ( and i am sure all others ) it gives a blank entity class when the file exists and the regenerateIfExists is set to true, the expected result would be a full entity with any removed columns removed from the entity and new columns to be added.

i've come up with a fix that i assume is the correct way
i haven't tested this without the regeneration set to true since my application requires the regeneration, here's my code block i'm using:

$em->getConfiguration()->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\SesXmlDriver(
'ext/Doctrine/Entities/xml_metadata/'
)
);

$cmf = new Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();

$generator = new \Doctrine\ORM\Tools\EntityGenerator();
$generator->setGenerateAnnotations(true);
$generator->setGenerateStubMethods(true);
$generator->setRegenerateEntityIfExists(true);
//$generator->setUpdateEntityIfExists(true);
$generator->generate($metadata, 'ext/');

in the _hasProperty and _hasMethod functions, need to add the below to the inline check:

( ! $this->_isNew && $this->_regenerateEntityIfExists)


 Comments   
Comment by Benjamin Eberlei [ 02/Feb/11 ]

blank as in the file is completly empty?

Comment by Stephen Walker [ 02/Feb/11 ]

no, it generates just the class with no properties or methods.

Comment by Benjamin Eberlei [ 02/Feb/11 ]

Fixed





[DDC-1002] bug in generate entities with many2many relationships from xml/yml shcemes Created: 25/Jan/11  Updated: 02/Feb/11  Resolved: 02/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Stepan Tanasiychuk Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Linux stfalcon-laptop 2.6.35-22-generic #35-Ubuntu SMP Sat Oct 16 20:45:36 UTC 2010 x86_64 GNU/Linux
Installed packages, channel pear.doctrine-project.org:
======================================================
Package Version State
DoctrineCommon 2.0.0 stable
DoctrineDBAL 2.0.0 stable
DoctrineORM 2.0.0 stable


Attachments: GZip Archive Entities.tar.gz     GZip Archive yml.tar.gz    

 Description   

I try use many2many relations in my symfony2 learning project https://github.com/symfony/symfony.git
But entities thar generates from yml schemes did not meet entities from doctrine2 guide or entities from beberlei Whitewashing project https://github.com/beberlei/Whitewashing/tree/master/Blog

After that I try generate similar entitries is doctrine2-sandbox. Problem is the same
I attached yml schemes and result entities.

Problem:

  • Entities\Address does not have relations with Entities\User
  • In Entities\User property $adresses instance of Entity\Address. But this Doctrine\Common\Collections\ArrayCollection or no?
        /**
         * @var Entity\Address
         */
        private $addresses;
  • In Entities\User not at __constructor() method:
        public function __construct()
        {
            $this->addresses = new ArrayCollection();
        }


 Comments   
Comment by Benjamin Eberlei [ 02/Feb/11 ]

Fixed the msising constructor. However mind that in my Whitewashing project i wrote the entities manually, not generated them!





[DDC-997] Call to undefined method isIdentifier in AbstractHydrator.php line 197 Created: 23/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed





[DDC-996] Empty field names lead to weird exception Created: 23/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Empty field names (possible in xml and yml) lead to weird exception messages, they should throw a MappingException::missingFieldName exception.



 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed





Query getSingleResult throws inappropiate exceptions. (DDC-942)

[DDC-991] Add method "getFirstResult()" that returns null on no result Created: 18/Jan/11  Updated: 31/Mar/11  Resolved: 31/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

There are some requests for a method on Query that return a first result or null.



 Comments   
Comment by Benjamin Eberlei [ 31/Mar/11 ]

Implemented as "getOneOrNullResult". This way it clearly stands out against getSingleResult() and you cannot mess them up





[DDC-982] Make SQLWalker::getSQLTableAlias() more unique with dql aliases Created: 13/Jan/11  Updated: 20/Feb/11  Resolved: 20/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0, Git Master
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Critical
Reporter: Benjamin Eberlei Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

getSqlTableAlias: $tableName .= $dqlAlias;

say there is a guy who has two tables "user" and "users" and he does SELECT * FROM User s



 Comments   
Comment by Guilherme Blanco [ 19/Feb/11 ]

Fixed in trunk

Comment by Benjamin Eberlei [ 20/Feb/11 ]

Reopened, because i cant change variables in a closed vs a resolved ticket anymore.





[DDC-980] SQL alias behavior inconsistent in UPDATE ... WHERE (subselect) Created: 13/Jan/11  Updated: 13/Jan/11  Resolved: 13/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Lee Feistel Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When using a DQL UPDATE with a subselect in the WHERE clause (such as what the size() function generates), the subselect is trying to reference an alias that is not defined in the main UPDATE clause. Using the size() function similarly in a SELECT statement works fine, the problem is only occurring for me when I try an UPDATE. I have not tried it with INSERT or DELETE, but I would suspect a similar inconsistency with anything other than the more common usage with SELECT.

$q = $em->createQuery('UPDATE Event e SET e.no_speakers = 1, e.no_credits = 1 WHERE size(e.Instances) = 0');
print $q->getSQL();

Output:

UPDATE Event SET no_speakers = 1, no_credits = 1 WHERE (SELECT COUNT(*) FROM Instance c0_ WHERE c0_.Event_id = c1_.id) = 0

And, $q->execute() results in:

PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'c1_.id' in 'where clause'' in /var/www/v3-lf/library/Doctrine/DBAL/Connection.php:657
Stack trace: #0 /var/www/v3-lf/library/Doctrine/DBAL/Connection.php(657): PDO->exec('UPDATE Event...')


 Comments   
Comment by Benjamin Eberlei [ 13/Jan/11 ]

Would something like the following work on ALL database vendors?

UPDATE Event SET no_speakers = 1, no_credits = 1 WHERE (SELECT COUNT(*) FROM Instance c0_ WHERE c0_.Event_id = Event.id) = 0
Comment by Benjamin Eberlei [ 13/Jan/11 ]

It does work. Fixed!





[DDC-978] Many-To-Many relations are removed after Flush() Created: 12/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Thomas G. Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 2
Labels: None

Attachments: File sandbox.rar    
Issue Links:
Duplicate
is duplicated by DDC-983 Creating new collection for manyToMan... Resolved

 Description   

Let's say we have three entities: User, Channel, and Log

Every time a User is created or updated, Channels are assigned to a Many-To-Many collection.
This action gets logged in the Log entity.

I have reproduced the bug in the Doctrine sandbox (see attachment). It's a fully working example.
This is a summary:

This works
// Fetch two channels in an array
$channels = .......

// create a new user and assign channels
$user = new User();
$user->setName('FooBar');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
This also works
// Fetch two channels in an array
$channels = .......

// fetch an existing user, *change something to the user*, and assign channels
$user = .............
$user->setName('Gaz');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
This does not work (channels are removed)
// Fetch two channels in an array
$channels = .......

// fetch an existing user and only assign channels, change nothing else
$user = .............
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();

This last piece of code generates following SQL code (summarized):

DELETE FROM user_channels WHERE userId = 1
INSERT INTO user_channels (userId, channelId) VALUES (1, 2);
DELETE FROM user_channels WHERE userId = 1

If you remove the $em->flush() after $em->persist($user); in the last example, the code works (channels are persisted).

I did not have this problem with Doctrine2 Alpha4.



 Comments   
Comment by Benjamin Eberlei [ 12/Jan/11 ]

What do you do in "setChannels"? Do you completly overwrite the previous content of the association variable "User::$channels" ?

Comment by Thomas G. [ 12/Jan/11 ]

I have reproduced the bug in a fully working example. See attachment. Just read instructions in comment and execute each step seperately.

But yes, I overwrite the previous content of the association variable "User::$channels" with a Doctrine ArrayCollection.

User Entity
/** @Entity @Table(name="users") */
class User
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;
    /** @Column(type="string", length=50) */
    private $name;

    /**
     * @ManyToMany(targetEntity="Channel")
     * @JoinTable(name="users_channels",
     *          joinColumns={@JoinColumn(name="userId",
                referencedColumnName="id")},
     *          inverseJoinColumns={@JoinColumn(name="channelId",
     *          referencedColumnName="id")}
     *      )
     * @var ArrayCollection
     */
    protected $channels;

    public function __construct(){
        $this->channels = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getChannels() {
        return $this->channels;
    }

    public function setChannels($channels) {
        $channels =  new \Doctrine\Common\Collections\ArrayCollection($channels);
       
        $this->channels = $channels;
    }
}
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed.





[DDC-969] SchemaTool fails with class table inheritance if id columnName is not "id" Created: 05/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Trivial
Reporter: ayhan Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

In method getSchemaFromMetadata() within the $class->isInheritanceTypeJoined() part the following line

Doctrine\ORM\Tools\SchemaTool::getSchemaFromMetadata() — Line 182
$table->getColumn($class->identifier[0])->setAutoincrement(false);

leads to a Doctrine\DBAL\Schema\SchemaException::columnDoesNotExist() if a columnName other then id is used for the id field, as not the columnName (but the field name) is passed to $table->getColumn().

Should rather be

$table->getColumn($columnName)->setAutoincrement(false);


 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed





[DDC-968] Query hints should be retrievable by user Created: 03/Jan/11  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: Git Master
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Gediminas Morkevicius Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

all



 Description   

Currently the only way to set additional parameters accessible by AST TreeWalker is using the query hints.
the main problem is then query is being cloned, hints are flushed and the only way to set them is to access them by name and feed to cloned query one by one.
I think there should be Query::getHints() method available to the userland



 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Implemented





[DDC-966] SchemaTool does not check for inherited fields in STI sub-classes and overwrites their column definitions to DEFAULT NULL Created: 01/Jan/11  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: ayhan Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   
Example
/**
 * @Entity
 * @Table(
 *     name="eav_attribute",
 *     uniqueConstraints={
 *         @UniqueConstraint(columns={"core_project_id", "name"})
 *     }
 * )
 * @InheritanceType(
 *     "SINGLE_TABLE"
 * )
 * @DiscriminatorColumn(
 *     name="datatype",
 *     type="string"
 * )
 * @DiscriminatorMap({
 *     "datetime"="AttributeDatetime",
 *     "decimal"="AttributeDecimal",
 *     "int"="AttributeInt",
 *     "string"="AttributeString",
 *     "text"="AttributeText"
 * })
 */
abstract class AbstractAttribute
{
    // ...
    
    /**
     * @Column(type="string")
     */
    protected $name;

    /**
     * @Column(type="boolean")
     */
    protected $is_unique;

    // ...
}

/**
 * @Entity
 */
class AttributeDatetime extends AbstractAttribute
{
}

Expected SQL-dump:

name VARCHAR(255) NOT NULL,
is_unique TINYINT(1) NOT NULL,

SQL-dump created by SchemaTool:

name VARCHAR(255) DEFAULT NULL,
is_unique TINYINT(1) DEFAULT NULL,

This behaviour is problematic, especially for columns which are part of a unique constraint.

Reason:

SchemaTool doesn't really check for inherited fields in STI sub classes in method getSchemaFromMetadata() and passes all fields (incl. the inherited) to method _gatherColumn() where finally the column definition of the parent class will be overwritten.

Doctrine\ORM\Tools\SchemaTool
private function _gatherColumn($class, array $mapping, $table)
{
    // Lines 309 - 311
    if ($class->isInheritanceTypeSingleTable() && count($class->parentClasses) > 0) {
        $options['notnull'] = false;
    }
}

A quick fix:

Change that if-clause above to

if ($class->isInheritanceTypeSingleTable() && count($class->parentClasses) > 0 && ! isset($mapping['inherited'])) {

Better fix:

Only pass not inherited fields to the _gatherColumn() method, as done with CTI sub classes.



 Comments   
Comment by Benjamin Eberlei [ 02/Jan/11 ]

Fixed

Comment by ayhan [ 02/Jan/11 ]

Wow, that was fast!





[DDC-965] Check for ID in CMF should be done after Event invocation Created: 01/Jan/11  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0, Git Master
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Benjamin Eberlei [ 02/Jan/11 ]

Fixed





Several features to batch eager selects more efficently (DDC-952)

[DDC-963] @OneToOne inverse side executes queries even if object is in IdentityMap Created: 31/Dec/10  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0, Git Master
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Critical
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Benjamin Eberlei [ 16/Mar/11 ]

Merged





[DDC-961] First letters are missing in M:N tables Created: 30/Dec/10  Updated: 30/Dec/10  Resolved: 30/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Jakub Vrána Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Windows, MySQL



 Description   

When I define M:N relation and update the schema by SchemaTool then the joining table is created without first letters (e.g. rticle_ag instead of article_tag). Relevant part from the source code:

<?php
/** @entity */
class Article {
	/** @manyToMany(targetEntity="Tag") */
	public $tags;
}

/** @entity */
class Tag {
	/** @manyToMany(targetEntity="Article", mappedBy="tags") */
	public $articles;
}

$tool = new \Doctrine\ORM\Tools\SchemaTool($em);
$tool->updateSchema(array(
	$em->getClassMetadata('Article'),
	$em->getClassMetadata('Tag'),
));
?>

You can download the complete example at http://www.notorm.com/static/doctrine2-notorm/



 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

Your entities are not namespaced are they?

Comment by Benjamin Eberlei [ 30/Dec/10 ]

Yes, this is related to entities in global namespaces only. That is why nobody realized it before.

Fixed now.





[DDC-960] Locking @Version with MappedSuperClass and Single Table Inheritance results in wrong queries Created: 30/Dec/10  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Jack van Galen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Windows 7 using Zend Server



 Description   

When using a @version field for locking purposes in one of the fields of a MappedSuperClass, things go wrong. Here is my situation:

SpecificUser extends of BaseUser
There is one mapped superclass containing things like createdOn, createdBy and finally the @version field named version.

Now, when I change a record, the following queries are created. The last one is faulty:

Query: UPDATE specificuser SET firstname = ? WHERE id = ?
Query: UPDATE baseuser SET version = version + 1 WHERE id = ? AND version = ?
Query: SELECT version FROM specificuser WHERE id = ? <======= should be: SELECT version FROM baseuser WHERE id = ?



 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

You say Single Table Inheritance but specificuser and baseuser are two different tables? How does that work? With single table inheritance both specificuser and baseuser are in the same table.

Can you post your mappings? I am not convinced of this bug yet

Comment by Jack van Galen [ 04/Jan/11 ]

Oops, my mistake. I meant to say 'class table inheritance'. The definitions that I used (slightly modified and translated to English) are below.

Unable to find source-code formatter for language: php. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
 
namespace framework{

	/** @MappedSuperclass */
	class DbTable {

		/**
		 * @Id @Column(type="integer", name="id", length="10", unique="", nullable="")
		 * @GeneratedValue(strategy="AUTO")
		 */
		private $id;

		/** @Version @Column(type="integer", name="version", nullable="true") */
		private $version;
		
		/** @Column(type="datetimetz", name="createdon", nullable="true") */
		private $createdon;

	}
	
}


namespace custom\tables{

	/**
	* @Entity
	*/
	class specificuser extends generated\tables\baseuser {
		
	}

}


namespace custom\tables{

	/**
	 * @Entity
	 * @InheritanceType("JOINED")
	 * @DiscriminatorColumn(name="discr", type="string")
	 * @DiscriminatorMap({"specificuser" = "custom\tables\specificuser"})
	 */
	class baseuser extends generated\tables\baseuser {
	
	}
	
}


namespace generated\tables{

	class specificuser extends custom\tables\baseuser {
	}
	
}


namespace generated\tables{

	class user extends framework\DbTable {

		/**
		*@Column(type="string", nullable="false", unique="true")
		*/
        protected $username;
		
	}
	
}
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed





[DDC-958] postLoad event triggering Created: 29/Dec/10  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Improvement Priority: Minor
Reporter: Gediminas Morkevicius Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

all



 Description   

Currently I've noticed that postLoad event is not triggered on $em->refresh($entity); it seems like entity should be reloaded on this call
and logically postLoad event should be also triggered if entity is being reloaded.



 Comments   
Comment by Benjamin Eberlei [ 23/Jan/11 ]

Fixed





[DDC-955] PostgresSQL + No identifier / primary key for Specified Entity 'Table'. Every Entity must have for an identifier / primary key. Created: 28/Dec/10  Updated: 30/Dec/10  Resolved: 30/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: John Carlos Espitia Rivera Assignee: Benjamin Eberlei
Resolution: Duplicate Votes: 0
Labels: None
Environment:

all



 Description   

PostgreSQL error map from reverse engineering is not recognized by the primary keys in PostgreSQL and throws the following error: "No identifier / primary key for Specified Entity 'Table'. Every Entity must have for an identifier / primary key."



 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

Duplicate of DDC-929





[DDC-953] CLI tools orm:generate-entities --regenerate-entities=1 flag will generate empty entities 50% of time. Created: 28/Dec/10  Updated: 08/Feb/11  Resolved: 08/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.0
Fix Version/s: 2.0.2, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Flyn San Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Ubuntu 10.10, PHP5.3.3



 Description   

Running the command:
doctrine orm:generate-entities --regenerate-entities=1 --generate-annotations=1 ./

50% of the time my entity will appear as:
<?php

namespace models;

/**

  • models\Role
    *
  • @Table(name="roles")
  • @Entity(repositoryClass="models\repositories\RoleRepository")
    */
    class Role
    {

}

The other 50% everything will be in there. In addition, if the --regenerate-entities=1 argument is removed, if I change the data in my YAML schema file for a column (such as changing length=255 to length=50 on a string), the annotations won't be updated when the updated entity is generated. It seems only new fields are being added to the entity files which is why --regenerate-entities=1 was required in the first place.



 Comments   
Comment by Benjamin Eberlei [ 02/Feb/11 ]

Fixed

Comment by Flyn San [ 08/Feb/11 ]

This issue is still not fixed in 2.0.1. Simply run orm:generate-entities --regenerate-entities=1 --generate-annotations=1 to replicate.

Comment by Benjamin Eberlei [ 08/Feb/11 ]

Yes, because this issue is fixed in 2.0.2 not in 2.0.1.





[DDC-949] strange behavior with boolean types when using findOneBy() in a CLI phpunit test Created: 25/Dec/10  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Closed
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Lukas Kahwe Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File DDC949Test.php     File DoctrineORMBugTest.php    

 Description   

I do not see this behavior when running findByOne() calls via the Apache SAPI. No clue really what could possibly cause this. Not sure how to get the error logger to output something in a phpunit test (never really figured out how phpunit supports debugging). Essentially if I run the tests with SQLite the case with 'false' fails and when I run with PostgreSQL the case with 0 fails. Essentially in the fail case I get an instance of $this, just like when I pass: false.

Tell me if this report is useless in the current state and then I will work on separating it out into a standalone CLI script without Symfony2 and phpunit. But I dont want to spend more time on this if it isnt necessary.



 Comments   
Comment by Benjamin Eberlei [ 28/Dec/10 ]

Cannot reproduce.

Comment by Benjamin Eberlei [ 28/Dec/10 ]

Attached simpler testcase for reproduce.

Comment by Lukas Kahwe [ 28/Dec/10 ]

further testing shows this issue only exists with false and there I can reproduce it on the CLI and via apache. it seems I am hitting: http://bugs.php.net/bug.php?id=33876
however the issue also happens with sqlite for the same reason false gets casted to an empty string when not telling PDO explicitly to handle the parameter as a boolean.

Comment by Lukas Kahwe [ 01/Jan/11 ]

as explained in the previous comment, the issue is caused by "false" and not by "true" as in the test case.

Comment by Benjamin Eberlei [ 02/Jan/11 ]

Fixed.

This issue occured, because BasicEntityPersister did not pass the PARAM: typehints to the DBAL connection.

Adding this fixes the issue with Booleans on PostgreSQL, however I just realized it also exists for Oracle OCI and needs an adjustment in DBAL to be fixable.

Comment by Lukas Kahwe [ 02/Jan/11 ]

I am also seeing the issue with SQLite.

Comment by Lukas Kahwe [ 02/Jan/11 ]

ok .. i can confirm the issue is fixed on sqlite and postgresql





[DDC-945] Crashing Bug: BasicEntityPersister::_getSelectColumnListSQL returns empty list, thus generating wrong SQL Created: 22/Dec/10  Updated: 14/Apr/12  Resolved: 28/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Minor
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I have a situation where Doctrine generates a wrong SQL query and crashes with an exception.

The userland code calls the EntityManager::merge method.

The query generated looks like "SELECT FROM SomeTable", meaning it has no select column list, and therefore it's plainly wrong.

The entity I am trying to merge back into the entity manager is a regular entity with state detached. The class has a column which is declared as ID and filled with an autogenerated value, three regular columns, and a one-to-many relationship. The to-many-relationship causes BasicEntityPersister::loadOneToManyCollection() to be called, which in turn calls BasicEntityPersister::_getSelectEntitiesSQL, which then calls BasicEntityPersister::_getSelectColumnListSQL, which wrongly returns an empty string, thus leading to the corrupt query without a select column list being generated. The target entity of the one-to-many relationship is a mapped superclass, which has an ID (again with autogenerated values), and a many-to-one relationship inversing the one in the first entity. Further fields depend on its exact type as determined by the inheriting entities, but it will always have some.

Here is the exception, up to the point where the trace leaves the ORM:

exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM VersionedDataObject t0' at line 1' in /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/DBAL/Connection.php:577 Stack trace: #0 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/DBAL/Connection.php(577): PDO->query('SELECT FROM Ve...') #1 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/Persisters/BasicEntityPersister.php(1173): Doctrine\DBAL\Connection->executeQuery('SELECT FROM Ve...', Array) #2 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/UnitOfWork.php(1984): Doctrine\ORM\Persisters\BasicEntityPersister->loadOneToManyCollection(Array, Object(persistentData\model\versioning\InputComponentDataVersion), Object(Doctrine\ORM\PersistentCollection)) #3 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/PersistentCollection.php(207): Doctrine\ORM\UnitOfWork->loadCollection(Object(Doctrine\ORM\PersistentCollection)) #4 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/UnitOfWork.php(1441): Doctrine\ORM\PersistentCollection->initialize() #5 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/UnitOfWork.php(1323): Doctrine\ORM\UnitOfWork->doMerge(Object(persistentData\model\versioning\InputComponentDataVersion), Array) #6 /var/www/invoiceCreator/src/thirdPartyComponents/doctrine/Doctrine/ORM/EntityManager.php(520): Doctrine\ORM\UnitOfWork->merge(Object(persistentData\model\versioning\InputComponentDataVersion))

This one is a blocker by user standards. The error means that it is impossible to use Doctrine in long-running batch jobs like in my situation, because it does not support merging certain detached objects back into the entity manager at all, while at some point they need to be detached for virtual memory capacity reasons.



 Comments   
Comment by Daniel Alvarez Arribas [ 22/Dec/10 ]

Added a more accurate description of both entities involved.

Comment by Benjamin Eberlei [ 22/Dec/10 ]

This is not enough information to reproduce this issue. We have tests that show merge and detach works. I need more code, mapping files and a reproduce set.

If yo udont want to attach it to the issue you can send me a mail.

Comment by Daniel Alvarez Arribas [ 25/Dec/10 ]

After analyzing the problem further, I think it is nothing but a subsequent error due to the bidirectional association in the mapped superclass, which is documented to not work in the first place, as relationships declared in mapped superclasses must be unidirectional. After changing the mapped superclass to a regular entity, the application is working.

The only remaining problem in this case is the crashing effect. This is due to the rudimentary data model validation combined with the total lack of decent error messages in Doctrine 2. As there is no apparent relationship between the symptom (exception due to incorrect SQL being generated) and the effective technical source of the problem (bidirectional relationship declared in a mapped superclass), it is unnecessarily cumbersome to determine what possible sources of error to look for. It would be great if doctrine could defend itself against non-conforming data model inputs by producing an understandable error message instead of just crashing.

I will leave this bug open as a validation issue.

Comment by Benjamin Eberlei [ 27/Dec/10 ]

Yeah this is annoying, i check if we can implement a cheap runtime validation when loading the class metadata.

Comment by Benjamin Eberlei [ 28/Dec/10 ]

Throwing mapping exception if using a mapped superclass with ManyToMany or OneToMany association now.

Comment by Daniel Alvarez Arribas [ 29/Dec/10 ]

Thanks for fixing this.

Shouldn't it actually only throw an exception when using bidirectional associations with a mapped superclass?

Comment by Benjamin Eberlei [ 31/Dec/10 ]

Not exactly but you are right, unidirectional Many To Many associations work if you use the Mapped Superclass only once. I will adjust the patch accordingly.

For 2.1 there will be an additional feature described in DDC-964 that allows overriding certain mapped superclass details to avoid these problems.

Comment by Benjamin Eberlei [ 31/Dec/10 ]

Corrected.

Comment by Benjamin Eberlei [ 22/Mar/12 ]

A related Github Pull-Request [GH-218] was
https://github.com/doctrine/doctrine2/pull/218

Comment by Benjamin Eberlei [ 14/Apr/12 ]

A related Github Pull-Request [GH-335] was opened
https://github.com/doctrine/doctrine2/pull/335





[DDC-944] MappingException::mappingNotFound() calls are wrong in ClassMetadataInfo Created: 21/Dec/10  Updated: 21/Dec/10  Resolved: 21/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Giorgio Sironi Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

As you can see in:
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
and:
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/MappingException.php
mappingNotFound() accepts now only 1 argument, but is called with 2; this leads to cryptic errors when the a field does not exist like:
Doctrine\ORM\Mapping\MappingException: No mapping found for field 'EntityClassName'



 Comments   
Comment by Benjamin Eberlei [ 21/Dec/10 ]

Fixed





[DDC-943] EntityRepository::findBy should support multiple values on criteria fetching Created: 20/Dec/10  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Minor
Reporter: Guilherme Blanco Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently it is impossible to execute a multiple value findBy on EntityRepository.

So supposing we have a Foo entity, we can do this:

$foos = $em->getRepository('Foo')->findByName('value');

But it is impossible to do:

$foos = $em->getRepository('Foo')->findByName(array('value1', 'value2'));

We have most of the support done inside BasicEntityPersister, but the _getSelectConditionSQL restricts to a single value by doing:

$conditionSql .= ' = ?'; at line 1150

We can extend the support easily by detecting array value and adding an IN (...) condition on this case.



 Comments   
Comment by Benjamin Eberlei [ 20/Dec/10 ]

This is not going into 2.0 anymore

Comment by Benjamin Eberlei [ 24/Dec/10 ]

Schedule for 2.1, there are some gotachs here though.

Comment by Benjamin Eberlei [ 16/Mar/11 ]

Implemented as part of DDC-952





[DDC-942] Query getSingleResult throws inappropiate exceptions. Created: 17/Dec/10  Updated: 18/Jan/11  Resolved: 17/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-ALPHA2, 2.0-ALPHA3, 2.0-ALPHA4, 2.0-BETA1, 2.0-BETA2, 2.0-BETA3, 2.0-BETA4, 2.0-RC1, 2.0-RC2
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Henrik Bjornskov Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None

Sub-Tasks:
Key
Summary
Type
Status
Assignee
DDC-991 Add method "getFirstResult()" that re... Sub-task Resolved Benjamin Eberlei  

 Description   

Currently when using the Query object or QueryBuilder there is no easy way to get the first found result with doing a lot of work. The method that seems to be for this purpose is getSingleResult but it throws an exception if no records are found and if there is more than one record found another Exception is thrown. This behavior is different than the ODM\MongoDB where null is returned.



 Comments   
Comment by Roman S. Borschel [ 17/Dec/10 ]
$items = $q->getResult();
$item = $items[0]; // if you're sure there is one...
// php 5.4?
$item = $q->getResult()[0];

The strict behavior of getSingleResult() is correct and desired. See the API documentation. It is for the cases where you know you want a single result and there is exactly a single result, and where everything else is an error. Getting the first object of a list of 0..* results is a different use-case and easily achieved as shown above.

ps. I don't really care how it is in the ODM as this behavior has been specified in the ORM long before that. Returning null in that case is definitely not a good thing to do imho.

Comment by Lukas Kahwe [ 12/Jan/11 ]

well .. there is also a use case for getting a single entity or null without an exception. note the key here is that i do not know that there will be a result and that my code doesnt explode if there is no result. as a result most of my repositories end up having a method for this purpose.

protected function getOneResult(\Doctrine\ORM\Query $query)

{ $result = $query->getResult(); return isset($result[0]) ? $result[0] : null; }




[DDC-931] SchemaTool->dropSchema fails if the given schema doesn't exist Created: 13/Dec/10  Updated: 22/Dec/10  Resolved: 22/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-RC2
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Timo A. Hummel Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

SchemaTool->dropSchema's documentation says:

 
Drops the database schema for the given classes.

In any way when an exception is thrown it is supressed since drop was issued for all classes of the schema and some probably just don't exist.

However, with a recent upgrade to 2.0-RC2, this doesn't work anymore. A PDO exception isn't caught if the specified table doesn't exist already.

 
exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1051 Unknown table 'UserAddress'' in /usr/share/php/Doctrine/DBAL/Connection.php:577

I'm not sure if this was caused by the ORM update or if it's maybe somewhere inside DBAL, which I upgraded at the same time.



 Comments   
Comment by Benjamin Eberlei [ 22/Dec/10 ]

Fixed





orm:convert-mapping (DDC-874)

[DDC-929] A index has to be named as "primary" to be detected Doctrine\ORM\Mapping\Driver\DatabaseDriver::loadMetadataForClass() Created: 13/Dec/10  Updated: 30/Dec/10  Resolved: 30/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.0-RC2
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Jiri Helmich Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

FreeBSD, PostgreSQL 8.4



 Description   

Condition

if (isset($indexes['primary']) && in_array($column->getName(), $indexes['primary']->getColumns())) {

needs the primary key to be named as primary. Discovered this when reverse engineering an existing database.

Fix, that worked for me:

Replace:

if (isset($indexes['primary']) && in_array($column->getName(), $indexes['primary']->getColumns())) {
$fieldMapping['id'] = true;

With:

$primary = false;

foreach ($indexes as $index)
{
if ($index->isPrimary())
{
if (in_array($column->getName(), $index->getColumns()))

{ $primary = true; break; }

}
}

if ($primary){
$fieldMapping['id'] = true;



 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

Fixed.





[DDC-928] Using uninitialised variable in lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php Created: 13/Dec/10  Updated: 28/Dec/10  Resolved: 28/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0-RC2
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Jiri Helmich Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

FreeBSD



 Description   

A call:

$metadata->setSequenceGeneratorDefinition($definition);

is performed a line above the definition of the $definition variable.

Fix: Switch those two lines:

// $metadata->setSequenceGeneratorDefinition($definition); //was here
$definition = array(
'sequenceName' => is_array($column['sequence']) ? $column['sequence']['name']:$column['sequence']
);
$metadata->setSequenceGeneratorDefinition($definition); //belongs here

On line 191 in RC2 release.



 Comments   
Comment by Benjamin Eberlei [ 28/Dec/10 ]

Fixed





Allow @Id on @ManyToOne fields (DDC-117)

[DDC-922] Persisting an entity with an 1:n collection of related entites fails if the FK ist part of a composite PK Created: 09/Dec/10  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: 2.0-RC1
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Florian Zumkeller-Quast Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Doctrine 2 RC 1 with sfDoctrine2Plugin using ORM, DBAL, Common and Symfony/Component for RC 1



 Description   

If you got two Entities A and B where A is a sample Entity with a 1:n relation to the Entity B
and B has a composite PK with the FK (A id) and a custom field like this:

EntityA:
  type: entity
  table: entity_a
  repositoryClass: EntityARepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    handle:
      type: string
      length: 32
      unique: true
 oneToMany:
    entites_b:
      targetEntity: EntityB
      mappedBy: entity_a
      cascade: [persist]
EntityB:
  type: entity
  table: entity_b
  repositoryClass: EntityBRepository
  id:
    description:
      type: string
      length: 255
      notnull: true
      generator:
        strategy: NONE
    entitiy_a_id:
      type: integer
      length: 11
      notnull: true
      generator:
        strategy: NONE
  fields:
    value:
      type: string
      length: 255
  manyToOne:
    entitiy_a:
      targetEntity: EntitiyA
      inversedBy: entities_b
Class EntityA
{
    private $id;
    
    private $handle;
    
    private $b_coll;
    
    public function addB(EntityB $ent) 
    {
        $this->b_coll->add($ent);
        $b->setA($this);
    }
}
Class EntityB
{
    private $description;
    private $entity_a_id;
    
    private $value;
    
    private $entity_a;
    
    public function setA(EntityA $ent)
    {
        $this->entity_a = $ent;
    }
}

If you try to persist an object of A holding one or more references to objects of B, the objects get correctly persistet. This means, that every inserted record of B has a correctly filled field "entity_a_id". The objects of B also have a correct reference to A holding now the new A record with its autoinc id.
But the object property "entity_a_id" stays empty. This leads to a collection of unusable EntityB objects (in memory), since on another persist of EntityA the values of entity_a_id are still not set correctly but the state is managed which leads to an "update B ... where entity_a_id=0"
We've tried to set the entity_a_id with an event handler on postPersist. On a persist of EntityA the collection entities wanted to update their entity_a_ids from 0 to the correct one.



 Comments   
Comment by Benjamin Eberlei [ 10/Dec/10 ]

Fixed formating

Comment by Benjamin Eberlei [ 10/Dec/10 ]

When dealing with foreign keys as composite keys you are currently forced to make use of the "Assigned Id Generator".

This means you have to make sure the IDs are set to their values before calling ->persist().

Comment by Benjamin Eberlei [ 10/Dec/10 ]

This issue will be fixed when DDC-117 is merged into master. That will happen for the 2.1 release.

Comment by Benjamin Eberlei [ 02/Jan/11 ]

Implemented





Several features to batch eager selects more efficently (DDC-952)

[DDC-914] Use JOIN for Fetch=EAGER ManyToOne and OneToOne in Persisters Created: 24/Dec/10  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

Currently Fetch=EAGER Only leads to proxies not being used, no optimizations are being done.

Optimizations could maybe be done easily for the cases:

1. Basic Entity Persister + ManyToOne
2. Basic Entity Persister + OneToOne + Owning side
3. Basic Entity Persister + OneToOne + Inverse side

Complicated cases would be:

  • Everything Single and JoinTableInheritance?
  • OneToMany and ManyToMany collections.


 Comments   
Comment by Benjamin Eberlei [ 16/Mar/11 ]

Merged





[DDC-892] Caches can potentially return false positives due to use of MD5 hash codes as keys. A classic. Created: 25/Nov/10  Updated: 23/Jan/11  Resolved: 23/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Critical
Reporter: Daniel Alvarez Arribas Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

I was just checking the execution path for efficiency and bumped into this block of code in /Doctrine/ORM/AbstracQuery.php,
starting on line 560:

protected function _getResultCacheId()
{
if ($this->_resultCacheId)

{ return $this->_resultCacheId; }

else

{ $sql = $this->getSql(); ksort($this->_hints); return md5(implode(";", (array)$sql) . var_export($this->_params, true) . var_export($this->_hints, true)."&hydrationMode=".$this->_hydrationMode); }

}

Of course, MD5 hashes can never be guaranteed to be unique, so this block of the doExecute-Method
starting on line 508 can return false positives and thus break the user's assumptions about the ORM's behavior:

// Check result cache
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
$id = $this->_getResultCacheId();
$cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id);

if ($cached === false)

{ // Cache miss. $stmt = $this->_doExecute(); $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll( $stmt, $this->_resultSetMapping, $this->_hints ); $cacheDriver->save($id, $result, $this->_resultCacheTTL); return $result; }

else

{ // Cache hit. return $cached; }

}

It is not likely to happen, but possible. Rely on it a couple of million times in a production system, and one day, eventually, it will fail
and hell will break loose.

I think it is prohibitive to try to save memory by giving up correctness. If your program does not work, it's simply broken and there is no need to tune it unless you fix it functionally.

The only safe solution would be to use a non-lossy hash (i. e. compression) method, if any. Plain query text would do fine too.

Unless you expect the user to anticipate false positives, i. e.



 Comments   
Comment by Daniel Alvarez Arribas [ 25/Dec/10 ]

Has anyone taken note of this one?

As it seems, this critical bug has been sitting here for a month, untouched, and apparently even made it into the final release.

I would offer to fix it myself, but as the fix would consist in removing just one or two MD5 hash method calls, and it would probably have to be validated anyway by a core developer, there is actually not much technical effort I could save you.

Just a reminder, thanks for your time.

Comment by Benjamin Eberlei [ 27/Dec/10 ]

The problem is rather that cache keys have a limited length depending on the cache driver.I know that Memcache limits at 255, have to look at the others.

Plain Text is not a solution, but we could build a range of several md5 or sha1 hashes to reduce the risk of false/positives even more.

Comment by Daniel Alvarez Arribas [ 29/Dec/10 ]

Hey Ben,

thanks for taking care.

I see the point about the length limitation. Still, I believe is a bad thing to subject correctness to probability considerations. Merely making it more unlikely to happen would only procrastinate a definite solution. Staying with a solution that relies on hash values being unique, is gambling with the probability of software systems malfunctioning randomly for no apparent reason, which is not a desirable outcome.

I figured out an alternate approach that IMO solves the length limit issue, while, to my knowledge, being correct. This is my first shot at it. But right now I do not see why this, or something like it, should not be feasible.

You could keep on indexing by MD5 hash value (just to guarantee an upper bound on the key length and circumvent the limits regarding the maximum key length). I think MD5 does that part quite well. But instead of just storing the value, store a map, mapping all of the original full-length keys that resolve to that common MD5 hash value to their individual values. In almost all but a few very rare cases, this map will have exactly one entry. Therefore in almost all cases, all that is retrieved from the cache is the value, plus the original key, enclosed in a map wrapper object. Needless to say, this map can be optimized for one entry. It could even be a list, with only a few bytes overhead. This solution would be almost as fast for read accesses as the most naïve cache implementation, but still work in cases where keys resolve to the same hash value.

The details are easy:

Fetching: Fetch the cache entry (the map) by the key's MD5 hash value. Then, look the correct value up in the map using the full-length key. Remember this is not any expensive operation. The map contains almost always exactly one value.

Creating: Fetch the cache entry (the map) by the key's MD5 hash value. If there is no cache entry at all, create a new map with a single entry in it and store it into the cache. If there is an entry, get the map, add the new entry to it using the full-length key and the value, and store the map back into the cache using the key's MD5 hash value. Adding a value to the map would also replace any existing entry for the full-length key in case it is already present in the map.

Deleting: Fetch the cache entry (the map) by the key's MD5 hash value. Then, use the full-length key to delete the corresponding value from the map. If the map is empty after removing the entry (and it will be almost always), delete the whole cache entry using the key's MD5 hash value.

This technique is correct always, and gives almost no overhead for reads. For writes and deletes, you have to fetch first, so there is an overhead, but right now I can't come up with anything faster
that isn't broken.

An optimization would be implementing an additional direct full-key mapping, too, for those cache providers supporting arbitrary length keys. This could give slightly better write performance when arbitrary-length keys are supported, as there would not be any map to be read in case of writing and deleting, just a direct cache operation.

Comment by Benjamin Eberlei [ 30/Dec/10 ]

The unhashed key could potentially be very large, which could lead to problems with the value limit of the caches. Plus the unhashed value relies on print_r(), thus on whitespace formatting which i wouldn't call exactly reliable.

We need to find a better solution to fix this

Comment by Daniel Alvarez Arribas [ 01/Jan/11 ]

As for the size limit on cached values, I think it is an independent problem, because any value size limit applies in any case, whether or not you implement unique keys or not. Currently, it also applies e. g. to query results, for which an upper size limit can not be guaranteed in general. Consequently, a strategy for handling such a limit is required anyway.

The naïve solution for handling the value size limit would be to simply not cache any values with a total size larger than the value size limit of the respective cache. As the value size limit should actually be reasonably large (memcached e.g. has a default limit of 1 MB), and the limitation is inherent to the cache, this should be perfectly plausible, because it is the caches key functionality that imposes the limit, not Doctrine. I believe the naïve solution is on-the-spot here, and would recommend to strictly opt against taking further measures (like splitting cache entries into buckets) to work around the problem. Working around this limit should have been implemented in the respective cache in the first place, not in Doctrine, as it concerns the caches key functionality. IMO the ORM should not duplicate cache functionality, rather use it in a proper way.

But after all, this is an unrelated problem, and it does not affect the point of this bug in any way.

As for the reliance on print_r: If you consider it to be non-deterministic (producing different output formattings for identical objects) it would be broken (possibly by design). That being said, I do not believe print_r() is non-deterministic by design, though the exact workings of it might not be formally specified. The formatting in the return value string should not introduce ambiguity into the representations of otherwise unique values, and neither produce different values for identical objects. As long as these conditions are met, you should be safe using it for generating cache keys. If not, use something that does fit. This is a mere implementation issue, anyway. You could also strip whitespaces (provided this does not affect uniqueness), to eliminate the whitespace factor.

If cache size efficiency of stored values is an issue, you could be well-advised to support compressing cache values (losslessly, of course) as an option.

Comment by Benjamin Eberlei [ 05/Jan/11 ]

Ok, the common recommendation to avoid cache collisions is using a multitude of different hashes and combine them, or use a very large hash.

So the best solution here is probably to switch to a cache key that has "sha1 + md5 + crc32" of the input and if ext/hash is installed use something much more powerful like sha256.

Comment by Daniel Alvarez Arribas [ 05/Jan/11 ]

That "recommendation" you are referring to might be just the common practice of using a combination of various hash values to increase the accuracy of ensuring data integrity and authenticity (e.g. by providing various different hash values for downloaded files). IMO this practice is feasible only for purposes like those, and can not be relied on if what you want to do is obtain correct results on cache lookups. While a change in hash value means that the file has definitely been modified (compared to the original) it does not imply e. g. that various modified files that have the same hash value have actually the same modified content.

What you are trying to do could be used in situations where a Bloom Filter (http://en.wikipedia.org/wiki/Bloom_filter) could be appropriately used, which is basically such a combination of various hashes. This could perfectly be used to determine whether there is a high chance that a specific value is in the cache. Such information could be useful to optimize disk accesses or costly requests to remote caches. Bloom filters are used e.g. in the Squid Caching HTTP Proxy, but certainly not for keying, rather for cache digests (read: "is it likely that this key is in the cache?"). This is not the case with the Doctrine 2 caches - these should better be 100% reliable.

Increasing the number or size of hash values will just decrease the probability of a crash, but will not ultimately fix the problem (unless you make the hash values include all original information, but that would be pointless in the first place). And that something is unlikely to happen does not mean it will necessarily take a long time to actually happen. It could as well break an application tomorrow.

Seriously, I do not know of any theoretically backed recommendation that tolerates wrong results when correctness is expected. There are a couple of approximation techniques appropriate in situations where false positives are anticipated, but I believe no such technique would be an appropriate solution for your situation, simply because no one expects the programming contract to imply having to anticipate false positives.

But of course, various hashes would still be better than one, though still worth a bug. Personally I would always opt for correctness. Do as you like.

Comment by Benjamin Eberlei [ 23/Jan/11 ]

Implemented separate chaining to avoid hash key collisions.





[DDC-887] Schema tool can throw errno 121 when creating or dropping indexes Created: 22/Nov/10  Updated: 19/Jun/11  Resolved: 19/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

When changing the model in such a way that the schema tool tries to create or drop an index which is also a foreign key an error is sometimes thrown like:

[PDOException]
SQLSTATE[HY000]: General error: 1025 Error on rename of '.\mydb#sql-10d8_19' to '.\mydb\auth' (errno: 121)

This seems to be caused by MySQL trying to re-use indexes and I think it depends on exactly what has happened before in this table so I can't give an exact case to reproduce. However, it seems to be InnoDB specific and I'm pretty sure its this bug: http://bugs.mysql.com/bug.php?id=15317



 Comments   
Comment by Dave Keen [ 22/Nov/10 ]

Another report of the issue at http://bugs.mysql.com/bug.php?id=14347

Comment by Benjamin Eberlei [ 19/Jun/11 ]

Fixed





Allow @Id on @ManyToOne fields (DDC-117)

[DDC-881] DDC-117: Linked Objects with composite key Created: 18/Nov/10  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Minor
Reporter: Timo A. Hummel Assignee: Roman S. Borschel
Resolution: Fixed Votes: 0
Labels: None


 Description   

I'm currently playing around with DDC-117. I came across a general
problem which occurs with relations.

Given the following two classes, should a
@OneToOne/@OneToMany/@ManyToMany relation consider a composite ID or is
that not planned with DDC-117?

In the past, we assumed that an object is identified unique with an @Id
column. However, if we support composite keys, an object needs to be
identified by two or more columns, which we need to take into
consideration when building queries and foreign keys. Is that correct?

/**
 * @Entity
 */

class Document {
	/**
	 * @Id
	 * @Column(type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	private $id;

	/**
	 * @Id
	 * @Column(type="integer")
	 */
	private $version;

	/**
	 * @ManyToOne(targetEntity="Content")
	 * Enter description here ...
	 * @var unknown_type
	 */
	private $content;
}

/**
 * @Entity
 */
class Content {
	/**
	 * @Id
	 * @Column(type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	private $id;

	/**
	 * @Id
	 * @Column(type="integer")
	 */
	private $version;

	/**
	 * @ManyToOne(targetEntity="Document")
	 */

	private $document;
}

I know this might become a bit tricky, because $content refers to a
single instance of Content, but we actually need two columns to identify
it. That's how it looks if generated with Doctrine2 (DDC-117):

mysql> describe Document;
+------------+---------+------+-----+---------+-------+
| Field      | Type    | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| id         | int(11) | NO   | PRI | NULL    |       |
| version    | int(11) | NO   | PRI | NULL    |       |
| content_id | int(11) | YES  | MUL | NULL    |       |
+------------+---------+------+-----+---------+-------+
mysql> describe Content;
+-------------+---------+------+-----+---------+-------+
| Field       | Type    | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| id          | int(11) | NO   | PRI | NULL    |       |
| version     | int(11) | NO   | PRI | NULL    |       |
| document_id | int(11) | YES  | MUL | NULL    |       |
+-------------+---------+------+-----+---------+-------+

However, to make my example work, the tables would need to look the
following:

mysql> describe Content;
+------------------+---------+------+-----+---------+-------+
| Field            | Type    | Null | Key | Default | Extra |
+------------------+---------+------+-----+---------+-------+
| id               | int(11) | NO   | PRI | NULL    |       |
| version          | int(11) | NO   | PRI | NULL    |       |
| document_id      | int(11) | YES  | MUL | NULL    |       |
| document_version | int(11) | YES  |     | NULL    |       |
+------------------+---------+------+-----+---------+-------+
mysql> describe Document;
+-----------------+---------+------+-----+---------+-------+
| Field           | Type    | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+-------+
| id              | int(11) | NO   | PRI | NULL    |       |
| version         | int(11) | NO   | PRI | NULL    |       |
| content_id      | int(11) | YES  | MUL | NULL    |       |
| content_version | int(11) | YES  |     | NULL    |       |
+-----------------+---------+------+-----+---------+-------+

It would be nice if we could discuss this one, as I feel it is important for an ORM.



 Comments   
Comment by Benjamin Eberlei [ 18/Nov/10 ]

Hm i think this issue appears becaues "version" in your mapping is defined twice in the "Content" entity.

You have rename the join column and it should work. Howevr ClassMetadata should throw an exception.

Comment by Timo A. Hummel [ 18/Nov/10 ]

So in theory, doctrine should handle my example with DDC-117? Will try that out later with unique field names and report back. If that would work already, this would be amazing!

Comment by Benjamin Eberlei [ 18/Nov/10 ]

btw your mapping is somewhat wrong. you cannot have two @ManyToOne that connect the same two entities with each other. One has to be @OneToMany

Comment by Timo A. Hummel [ 24/Nov/10 ]

Benjamin, I finally had time to check out more things. In fact, Doctrine with DDC-117 completely ignores multiple foreign keys.

Even if I replace @ManyToOne with @OneToMany, and version with fversion in Content, Doctrine still only creates a reference (and columns!) with content_id only. I would have expected that that I find at least content_id and content_version within the Document table

I also tried to specify mappedBy="document,version", but this also didn't work.

So again the question: Is my initial example meant to be possible with DDC-117, or is it not?

Comment by Timo A. Hummel [ 24/Nov/10 ]

I just created a better test.

User.php
<?php
/**
 * @Entity
 */
class User {
	/**
	 * @Id
	 * @Column(type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	private $id;
	
	/**
	 * @Column(type="string")
	 */
	private $name;
	
	/**
	 * @OneToMany(targetEntity="PhoneNumber",mappedBy="id")
	 */
	private $phoneNumbers;
}
PhoneNumber.php
<?php
/**
 * @Entity
 */
class PhoneNumber {
	/**
	 * @Id
	 * @Column(type="integer")
	 */
	private $id;
	
	/**
	 * @Id
	 * @ManyToOne(targetEntity="User",cascade={"all"})
	 */
	private $user;
	
	/**
	 * @Column(type="string")
	 */
	private $phonenumber;
	
	public function setId ($id) {
		$this->id = $id;
	}
	
	public function setUser (User $user) {
		$this->user = $user;
	}
	
	public function setPhoneNumber ($phoneNumber) {
		$this->phonenumber = $phoneNumber;
	}
}
PhoneCall.php
<?php 
/**
 * @Entity
 */
class PhoneCall {
	/**
	 * @Id
	 * @Column(type="integer")
	 * @GeneratedValue(strategy="AUTO")
	 */
	private $id;
	
	/**
	 * @OneToOne(targetEntity="PhoneNumber",cascade={"all"})
	 */
	private $phonenumber;
	
	/**
	 * @Column(type="string",nullable=true)
	 */
	private $callDate;
	
	public function setPhoneNumber (PhoneNumber $phoneNumber) {
		$this->phonenumber = $phoneNumber;
	}
	
}

This is a very basic mapping example, where one user may have many phone numbers. Also we have a PhoneCall entity which stores the call made. Since a single phone number isn't just identified by id, but also by user_id, Doctrine should create two fields in PhoneCall for that relation: phonenumber_id and phonenumber_user_id, so that we can retrieve the PhoneNumber object by PhoneCall's phonenumber property.

If you agree that my example should be working, I'm willing to write a test case and see if I can contribute code to make that happen.

Comment by Timo A. Hummel [ 24/Nov/10 ]

I'm preparing a real-world test script; no need to respond for now.

Comment by Timo A. Hummel [ 25/Nov/10 ]

As promised, here's the real-world test script. Note that I adjusted the code for the example entities due to DDC-891.

Test Script
/* Create two test users: albert and alfons */
$albert = new User;
$albert->setName("albert");
$em->persist($albert);

$alfons = new User;
$alfons->setName("alfons");
$em->persist($alfons);

/* Assign two phone numbers to each user */
$phoneAlbert1 = new PhoneNumber();
$phoneAlbert1->setUser($albert);
$phoneAlbert1->setId(1);
$phoneAlbert1->setPhoneNumber("albert home: 012345");
$em->persist($phoneAlbert1);

$phoneAlbert2 = new PhoneNumber();
$phoneAlbert2->setUser($albert);
$phoneAlbert2->setId(2);
$phoneAlbert2->setPhoneNumber("albert mobile: 67890");
$em->persist($phoneAlbert2);

$phoneAlfons1 = new PhoneNumber();
$phoneAlfons1->setId(1);
$phoneAlfons1->setUser($alfons);
$phoneAlfons1->setPhoneNumber("alfons home: 012345");
$em->persist($phoneAlfons1);

$phoneAlfons2 = new PhoneNumber();
$phoneAlfons2->setId(2);
$phoneAlfons2->setUser($alfons);
$phoneAlfons2->setPhoneNumber("alfons mobile: 67890");
$em->persist($phoneAlfons2);

/* We call alfons and albert once on their mobile numbers */
$call1 = new PhoneCall();
$call1->setPhoneNumber($phoneAlfons2);
$em->persist($call1);

$call2 = new PhoneCall();
$call2->setPhoneNumber($phoneAlbert2);
$em->persist($call2);

$em->flush();

During the flush, Doctrine fails with

Integrity constraint violation: 1062 Duplicate entry '2' for key 'PhoneCall_phonenumber_id_uniq

because Doctrine does not create the composite primary key (which is id and user_id) as foreign key (Doctrine only adds id).

Comment by Benjamin Eberlei [ 28/Dec/10 ]

The problem here is your @OneToOne relation. It implicitly sets a unique index. The primary key generated by your mapping is ok.

Try to modify your code stating @OneToOne(unique=false)

Additionally you have to specifiy the join columns. You are using the default, which obviously doesn't work for a composite approach (that is not default):

/**
 * @Entity
 */
class DDC881PhoneCall
{

    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @OneToOne(targetEntity="DDC881PhoneNumber",cascade={"all"})
     * @JoinColumns({
     *  @JoinColumn(name="phonenumber_id", referencedColumnName="id"),
     *  @JoinColumn(name="user_id", referencedColumnName="user_id")
     * })
     */
    private $phonenumber;
    /**
     * @Column(type="string",nullable=true)
     */
    private $callDate;

    public function setPhoneNumber(DDC881PhoneNumber $phoneNumber)
    {
        $this->phonenumber = $phoneNumber;
    }

}

That would be the right approach if there were not a bug in SchemaTool i need to fix for this to work

Comment by Benjamin Eberlei [ 29/Dec/10 ]

This is a really tricky issue, we need to think about it a little longer.

Comment by Benjamin Eberlei [ 02/Jan/11 ]

Fixed.





[DDC-874] orm:convert-mapping Created: 10/Nov/10  Updated: 30/Dec/10  Resolved: 30/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Cristian Rinaldi Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

Ubuntu 10.10.


Sub-Tasks:
Key
Summary
Type
Status
Assignee
DDC-929 A index has to be named as "primary" ... Sub-task Resolved Benjamin Eberlei  

 Description   

I have a Postgres SQL database.
The Base has only one table "User" with two attributes (name and id).
"Id" is primary key.

The failure to execute the task:
php orm doctrine: convert-mapping - from-database yml / home / cristian / database.yml

is:

[Doctrine \ ORM \ Mapping \ MappingException]
No identifier / primary key for Specified Entity 'User'. Every Entity must have for an identifier / primary key

Script to create the table:

CREATE TABLE "User"
(
id serial NOT NULL,
name character varying (55),
CONSTRAINT "User_pkey" PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
ALTER TABLE "User" OWNER TO postgres;



 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

Fixed in DDC-929





Several features to batch eager selects more efficently (DDC-952)

[DDC-865] Passing an array as parameter Created: 07/Nov/10  Updated: 16/Mar/11  Resolved: 16/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: DQL
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Jáchym Toušek Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File AlbumEntity.php     File IdEntity.php     File PictureEntity.php     File PictureRepository.php    

 Description   

First check the entites in attachments (I've deleted everything unnecessary for this example).

What I want to do is find multiple entities (I have their ids in array) and then do some action with each of them.

I'm trying to find those entites using IN operator in DQL query, but there is no way (or I was unable find it) to pass the array of ids as parameter to the query. I've tried several ways to do it (check the PictureRepository attachment) but none is working as i want. Further details are described in comments.

<?php
//I know i could use something like this but I wonder about the IN stetement right now. The example above is just for show.
foreach ($pictures as $value) {
$entity = $repository->find($value);
/...whatever i want to do with the $entity/
}
?>



 Comments   
Comment by Benjamin Eberlei [ 13/Mar/11 ]

This will be implemented as part of DDC-952

Comment by Benjamin Eberlei [ 16/Mar/11 ]

Implemented





[DDC-837] Two children in inheritance with same property name causes error in hydration Created: 12/Oct/10  Updated: 28/Dec/10  Resolved: 28/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Michael Ridgway Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Attachments: File DDC258Test.php    

 Description   

This is related to DDC-258. The issue seems to be fixed with regular column types (string, int, etc) but the same issue has cropped up when we have a OneToOne relationship in two child classes that share the same property name. I have modified the DDC258TestCase class to demonstrate the error.

To summarize: two classes that inherit from the same class happen to have a property with the same name. Both of them are oneToOne relationships. Querying for the objects, one object type (depending on discriminatorMap order) will be hydrate correctly but the other will always be null.



 Comments   
Comment by Benjamin Eberlei [ 13/Oct/10 ]

This is not a bug, its documented behavior and is technically not feasible.

Comment by Michael Ridgway [ 13/Oct/10 ]

Why would this not be feasible on relationships even though it is on regular column types? I feel like this is the same issue as DDC-258. I understand a child can't have a property named the same as the parent's, but two children should be able to have properties with the same name (and currently can if it's not a relationship).

Comment by Benjamin Eberlei [ 14/Oct/10 ]

oh maybe i am wrong

Comment by Benjamin Eberlei [ 28/Dec/10 ]

Fixed





Allow @Id on @ManyToOne fields (DDC-117)

[DDC-795] Wrong SQL statement when using loadOneToManyCollection Created: 09/Sep/10  Updated: 28/Dec/10  Resolved: 28/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Minor
Reporter: Van Hauwaert Bert Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Duplicate
duplicates DDC-117 Allow @Id on @ManyToOne fields Resolved

 Description   

I have the following SQL

CREATE TABLE `article` (
  `articleID` int(11) NOT NULL AUTO_INCREMENT,
  `reference` varchar(255) DEFAULT NULL,
  `addDt` datetime DEFAULT NULL,
  PRIMARY KEY (`articleID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


CREATE TABLE `articleRelated` (
  `articleID` int(11) NOT NULL,
  `relatedArticleID` int(11) NOT NULL,
  PRIMARY KEY (`articleID`,`relatedArticleID`),
  KEY `a1` (`articleID`),
  KEY `a2` (`relatedArticleID`),
  CONSTRAINT `a1` FOREIGN KEY (`articleID`) REFERENCES `article` (`articleID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `a2` FOREIGN KEY (`relatedArticleID`) REFERENCES `article` (`articleID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

And these 2 models

Article.php
<?php
/**
 * Model for article
 * 
 * @Table(name="article") 
 * @Entity
 */
class App_Model_Article
{

    /**
     * @var integer articleID
     * @Column(name="articleID", type="integer", nullable=false) 
     * @GeneratedValue(strategy="IDENTITY") 
     * @Id
     */
    protected $_articleID = null;

    /**
     * @var string reference
     * @Column(name="reference", type="string", nullable=true, length=255)
     */
    protected $_reference = null;

    /**
     * @var datetime addDt
     * @Column(name="addDt", type="datetime", nullable=true)
     */
    protected $_addDt = null;

    /**
     * @OneToMany(targetEntity="App_Model_ArticleRelated", mappedBy="_article", cascade={"persist"})
     */
    protected $_articleRelatedRefArticle = array();

    /**
     * @OneToMany(targetEntity="App_Model_ArticleRelated", mappedBy="_relatedArticle", cascade={"persist"})
     */
    protected $_articleRelatedRefRelatedArticle = array();
}

and

ArticleRelated.php
<?php

/**
 * Model for articleRelated
 * 
 * @Table(name="articleRelated") 
 * @Entity
 */
class App_Model_ArticleRelated
{

    /**
     * @ManyToOne(targetEntity="App_Model_Article") 
     * @JoinColumn(name="articleID", referencedColumnName="articleID") 
     * @Id
     */
    protected $_article = null;

    /**
     * @ManyToOne(targetEntity="App_Model_Article") 
     * @JoinColumn(name="relatedArticleID", referencedColumnName="articleID") 
     * @Id
     */
    protected $_relatedArticle = null;
}

When I do the following

$firstArticle = $this->_entityManager->find('App_Model_Article', 54);
      
$related = $firstArticle->getArticleRelated('article');
foreach ($related as $art) {
       	var_dump($art);
}

it generates the following SQL

SELECT , t1.articleID AS articleID0, t1.relatedArticleID AS relatedArticleID2 FROM articleRelated t1 WHERE articleID = ?

I tracked the problem down to the following method

Doctrine/ORM/Persisters/BasicEntityPersister.php
//...
protected function _getSelectColumnListSQL()
    {
        if ($this->_selectColumnListSql !== null) {
            return $this->_selectColumnListSql;
        }

        $columnList = '';

        // Add regular columns to select list
        foreach ($this->_class->fieldNames as $field) {
            if ($columnList) $columnList .= ', ';
            $columnList .= $this->_getSelectColumnSQL($field, $this->_class);
        }

        $this->_selectColumnListSql = $columnList . $this->_getSelectJoinColumnsSQL($this->_class);
		
        return $this->_selectColumnListSql;
    }
//....

Because $this->_class->fieldNames is empty for my class, $columnList will also be empty.
$this->_getSelectJoinColumnsSQL($this->_class) generates
", t1.articleID AS articleID0, t1.relatedArticleID AS relatedArticleID2"
so $this->_selectColumnListSql == ", t1.articleID AS articleID0, t1.relatedArticleID AS relatedArticleID2"

I fixed the problem by adding trim:

$this->_selectColumnListSql = trim($columnList . $this->_getSelectJoinColumnsSQL($this->_class), ',');


 Comments   
Comment by Benjamin Eberlei [ 10/Sep/10 ]

Foreign Keys as Primary Keys are currently not supported (except for the DDC-117 experimental branch, scheduled for 2.1)

See: http://www.doctrine-project.org/projects/orm/2.0/docs/reference/limitations-and-known-issues/en#current-limitations:foreign-keys-as-identifiers

Comment by Van Hauwaert Bert [ 10/Sep/10 ]

Sorry Benjamin, I should have mentioned that I work with that branch.

Comment by Benjamin Eberlei [ 12/Sep/10 ]

Ah ok, i'll move and downgrade priority because there is so much to do on the master branch before release.

Comment by Benjamin Eberlei [ 28/Dec/10 ]

Fixed in DDC-117 branch.





Several features to batch eager selects more efficently (DDC-952)

[DDC-734] Possibility to fetch all outstanding proxies of an Entity Created: 07/Aug/10  Updated: 30/Jul/13  Resolved: 16/Mar/11

Status: Closed
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Major
Reporter: Benjamin Eberlei Assignee: Guilherme Blanco
Resolution: Fixed Votes: 2
Labels: None


 Description   

For performance reasons (solving the N+1 problem) it might be necessary to load all proxy instances of a given type:

$orders = $em->getRepository('Order')->findAll();
foreach ($orders AS $order) {
   $order->getCustomer()->getId(); // n+1
}

However say we could do something like:

$orders = $em->getRepository('Order')->findAll();
$em->getUnitOfWork()->loadProxies("Customer");

foreach ($orders AS $order) {
   $order->getCustomer()->getId(); // n+1
}

This doesnt make too much sense in this case because we could use a fetch join with DQL. However you easily get to the point where you have a query like:

SELECT b, e, r, p FROM Bug b JOIN b.engineer e 
JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC

In this case the SQL generated is VERY huge and just the number of joins could cause an performance overhead. In general its better to keep the number of joins as small as possible, a solution here would optimize for the engineer and reporter being both instances of User:

$bugs = $em->createQuery("SELECT b, p FROM Bug b JOIN b.products p ORDER BY b.created DESC")->getResult();
$em->getUnitOfWork()->loadProxies("User"); // will load all engineers and reporters in one query

We could even make this nicer for using Queries:

$bugs = $em->createQuery("SELECT b, p FROM Bug b JOIN b.products p ORDER BY b.created DESC")
                        ->setQueryHint(Query::LOAD_PROXIES, array("User"))
                        ->getResult();


 Comments   
Comment by Benjamin Eberlei [ 16/Mar/11 ]

Implemented, but in another semantical way. Batching of eager loads of FETCH=EAGER associations aswell as AbstactQuery::setFetchMode($className, $assocName, $fetchMode) function to set this case-by-case for DQL.

Comment by Guilherme Blanco [ 30/Jul/13 ]

Closed

Comment by Konstantin [ 30/Jul/13 ]

I cann't find commit/branch where it was fixed





Several features to batch eager selects more efficently (DDC-952)

[DDC-733] Implement a way of forcing a PersistentCollection to initialize itself Created: 06/Aug/10  Updated: 05/Jun/11  Resolved: 05/Jun/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Minor
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 2
Labels: None

Issue Links:
Dependency
is required for DDC-1193 cascadeRemove misses associations due... Resolved

 Description   

Currently the only way to force an uninitialized collection to load itself is to call one of its methods (e.g. ->count()).

Roman suggested something like $em->initialize($collection)



 Comments   
Comment by Jonathan H. Wage [ 07/Aug/10 ]

Why not just make the initialize method public on PersistentCollection:

$collection->initialize();

??

Comment by Roman S. Borschel [ 07/Aug/10 ]

Even if that is done, userland code should not use the PersistentCollection API. Remember that a PersistentCollection is supposed to be a transparent wrapper around a Collection implementation. If a user calls $coll->initialize() this code implicitly assumes the concrete type of the collection to be PersistentCollection, which is not a good idea. Userland code should always program to the Collection interface.

Comment by Roman S. Borschel [ 07/Aug/10 ]

Such an initialize method should furthermore handle uninitialized proxies as well as uninitialized collections.

Comment by Dave Keen [ 07/Aug/10 ]

For extra points it might be nice if there was an extra cascade option for initialize, and possibly an event hook for pre and post initialize.

Comment by Eric Muyser [ 14/Mar/11 ]

I just ran into a bug with this, I believe. I have a Blog which cascade deletes it's Feeds. In cascadeDetach it's saying the count($relatedEntities) is zero for Feeds after the call to unwrap(), even though I know it to be, say, 1 or 2 (output before detaching owner entity). However, if I do ->count() or count($relatedEntities) BEFORE unwrap(), then PersistentCollection by consequence is initialized, and it cascade deletes correctly. If it don't, it actually says the Feeds are still MANAGED after having detached the owner entity. So, yeah, this or some other form of auto-initialization would be useful.

Note: In Blog, I have DQL which fetches Feeds JOINed to Blog, which may be causing the uninitialization (not sure). I'm using EXTRA LAZY LOADING.

Comment by James Harvey [ 20/Mar/11 ]

I have also run into a problem with this: when adding a single entity to an empty collection and then calling flush(), the collection which should now have 1 entity in it actually has 2. I discovered that this can be fixed by calling count() on the collection prior to the flush() operation. I looked into the code and noticed that most methods in PersistentCollection.php (v2.0.3) call $this->initialize() as their first step, but the add() function did not. I think this may be an oversight? By adding $this->initialize() to the add() function my problem was resolved.

Comment by Benjamin Eberlei [ 29/Mar/11 ]

Hello James, not calling initialize() is a very important performance optimization. Consider your collection containing hundrets, thousands or more entities. You dont want to load them all into memory just to add one new entity.

To solve your problem there is Collection::contains($entity) which will handle your collection correctly. in combination with "EXTRA_LAZY" support introduced in 2.1-DEV this is even very efficient.

Comment by Benjamin Eberlei [ 05/Jun/11 ]

Implemented $em->getUnitOfWork()->initializeObject().

For this the proxy method __load() was turned from private to public and marked as /** @private */





[DDC-701] Code generation for DQL queries Created: 20/Jul/10  Updated: 14/Mar/11  Resolved: 09/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Major
Reporter: Roman S. Borschel Assignee: Guilherme Blanco
Resolution: Fixed Votes: 0
Labels: None


 Description   

It would be cool to have the possibility to define DQL queries in the mapping documents and let these be precompiled to SQL via a command-line code-generation target that produces for each DQL query the SQL and ResultSetMapping in native PHP code.

This allows people to work without a query cache and maximum performance, on the cost of another code-generation step.

There are already named queries currently but these must be defined in the Configuration at runtime and thus it does not bear any advantages.
I would propose removing this runtime named query facility and replacing it with a "compile-time" one. So that "named queries" are queries defined in the mapping, given a name, which can optionally be precompiled via the CLI. If not precompiled a named query should be handled like a normal query.



 Comments   
Comment by Benjamin Eberlei [ 20/Jul/10 ]

I would keep the runtime named queries though. Its a very useful feature.

Comment by Guilherme Blanco [ 20/Jul/10 ]

The current implementation of named queries is not good.

I have recognized it previously and I was imagining a way to cast named queries related exclusively to direct EntityRepository.
Example:

$q = $em->getRepository('User')->getNamedQuery('findAll');
$users = $q->execute();

One of the ideas is to have a method called "initialize()' or something similar that would grab all Annotations from Metadata Mapping and automatically add them to the named query.

Example:

/**
 * @Entity
 * @NamedQueries({
 *     @NamedQuery(name="findAll', query="SELECT u FROM User u", hints=[...])
 * })
 * @NamedNativeQueries({
 *     @NamedNativeQuery(name="...", query="...", rsm=@ResultSetMapping(...))
 * })
 */
class User {
    // ...
}

Hibernate has a similar feature. So we have a reference to look at. =)

Comment by Roman S. Borschel [ 07/Aug/10 ]

Scheduled for 2.1 for now.

Comment by Guilherme Blanco [ 09/Mar/11 ]

This feature is not implemented and merged into ORM trunk. =)

Comment by Benjamin Eberlei [ 10/Mar/11 ]

There is still one feature missing here guilherme, the actual code generation. We need a task that dumps all named DQL into a SQL + RSM (what the cache is fed) into a single large file and grabs that file from an optional configuration (feature is optional).

What we need for this is implementation of __set_state() on RSM to use it with var_export(). We could also extend the DQL Run command to "compile" a single query with --compile or something then too.

Plus the change in $serialized is not made aswell.

Comment by Guilherme Blanco [ 14/Mar/11 ]

@beberlei

I don't think it is really necessary.
The main reason is because we already have a caching strategy here. If we keep the DQL, when developer uses it, it would automatically check for cache of SQL that was generated from first execution.

If the user attach a QueryCache to Configuration. We have nothing to do here.

As of compilation... we can do this, but is it a vital feature of this enhancement? I wouldn't consider it. It is good to have, but does the complexity of having it brings so many benefits?

Cheers,





[DDC-696] Add onClear Event Created: 19/Jul/10  Updated: 29/Mar/11  Resolved: 29/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-BETA2
Fix Version/s: 2.1
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

There should be an event "onClear" that is called whenever someone calls "EntityManager::clear()".

This may be necessary in certain long-running script scenarios when you have additional identity maps / caching, for example based on unique fields of an entity.



 Comments   
Comment by Roman S. Borschel [ 07/Aug/10 ]

Sounds like a new feature that is not urgent. Can we move that post 2.0?

Comment by Roman S. Borschel [ 08/Aug/10 ]

Moving to 2.1.

Comment by Michael Ridgway [ 24/Mar/11 ]

I posted a patch for this to Github at https://github.com/doctrine/doctrine2/pull/40

(I'm just making sure that this is logged to JIRA)

Comment by Benjamin Eberlei [ 29/Mar/11 ]

Merged mridgways branch, thank you!





[DDC-694] Add info Command that shows Entities and Mapping Directories Created: 18/Jul/10  Updated: 15/May/11  Resolved: 15/May/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

We should add an command to get information about the doctrine project:

  • List all entities
  • List all mapping directories/mapping drivers
  • Maybe configuration stuff?


 Comments   
Comment by Benjamin Eberlei [ 30/Dec/10 ]

Schedule for 2.1

This is very helpful for debugging, people tend to define their mappings wrong and its easy to tell them "check doctrine orm:list-mappings" or something

Comment by Benjamin Eberlei [ 15/May/11 ]

Implemented





Add the notion of read-only entities (DDC-209)

[DDC-692] Read-only entities Created: 15/Jul/10  Updated: 29/Mar/11  Resolved: 29/Mar/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: Sub-task Priority: Minor
Reporter: Roman S. Borschel Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None


 Description   

It should be possible to mark an entity class as read-only so that it is never considered for change-tracking after it has been initially inserted into the database.

This feature is mainly a flush performance tweak to avoid checking objects for changes which can never actually change.



 Comments   
Comment by Christian Heinrich [ 13/Sep/10 ]

Roman, could you point out how exactly you expect this to work?

I mean, when you create a new entity and persist it, you surely need to track updates to the entity-to-be-persisted.

Additionally, what about entities that are expected to be updated only in one place, like a service. Should there be a possibility to enforce updating?

Comment by Marc Hodgins [ 13/Sep/10 ]

For us, I see a use case for summary tables (i.e. Post and PostViews – a roll up of log data into computed "most popular", "most commented", views per day/week/month, etc). The data is generated outside of Doctrine (i.e. directly via DBAL, or stored procedures) but we still want to define the relationships of other entities to this data so we can access it on a read-only basis in DQL and the object graph. We would flag these as read-only as there is no need for change-tracking. Example:

/** @Entity */
class Post {
    /** @OneToMany(targetEntity="PostViews" ...) */
    protected $views;
}
/** @Entity @ReadOnly */
class PostViews { /* summary table computed via stored procedure */

   public function __construct() { throw new \Exception('Entity is read only'); }

    /** @Column */
    protected $period; // day, week, month, year, etc.

   /** @Column */
   protected $viewCount;
}

Regarding Roman's description of persist-only and then no updates, isn't this more like @PersistOnly rather than @ReadOnly? Or you could generalize this further with a tag like @AllowedActions={"persist", "update", "delete"} ?

/** @Entity @PersistOnly */
class A {
    /** @Column */
   protected $foo;
   
  public function __construct($foo) {
     $this->foo = $foo;
  }

  public function getFoo() {
    return $this->foo;
  }
}

Is this what you have in mind Roman?

Comment by Benjamin Eberlei [ 29/Mar/11 ]

Implemented.





[DDC-617] ObjectHydrator issue with OneToMany relationship Created: 30/May/10  Updated: 28/Dec/10  Resolved: 28/Dec/10

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-BETA1
Fix Version/s: 2.0.1, 2.1
Security Level: All

Type: Bug Priority: Major
Reporter: Numan S Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: None
Environment:

XAMPP 1.7.3 on Windows Vista


Attachments: File SocialMediaLink.php     File User.php    

 Description   

I'm pretty new to this ORM thing but I am having a weird issue with a DQL query I think should work (or throw an exception). I have the following code:

namespace Lms\Entities;
/**
 *
 * @Entity
 * @Table(name="User")
 */
class User {

	public function __constructor() {
		$social_media_links = new \Doctrine\Common\Collections\ArrayCollection;
	}
	/**
	 * @Id
	 * @Column(type="bigint")
	 * @GeneratedValue
	 */
	protected $id;

	/** @Column(type="string", nullable=TRUE, length=1024) */
	protected $mission_statement;

	/** @Column(type="string") */
	protected $first_name;

	/** @Column(type="string") */
	protected $last_name;

	/** @Column(type="string", nullable=TRUE, length=8) */
	protected $initial;

	/** @Column(type="string", nullable=TRUE) */
	protected $email;

	/** @Column(type="string", nullable=TRUE) */
	protected $company;

	/** @Column(type="string", nullable=TRUE, length=1024) */
	protected $picture;

	/** @Column(type="text", nullable=TRUE) */
	protected $bio;

	// unidirectional one to many relationship with social media link
	/**
	 * @ManyToMany(targetEntity="SocialMediaLink")
	 * @JoinTable(name="Users_Socialmedialinks",
	 *      joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
	 *      inverseJoinColumns={@JoinColumn(name="socialmedialink_id", referencedColumnName="id", unique=true)}
	 *      )
	 */
	protected $social_media_links;
	

    /**
     * Add social_media_links
     *
     * @param SocialMediaLink $socialMediaLinks
     */
    public function addSocialMediaLinks(\SocialMediaLink $socialMediaLinks)
    {
        $this->social_media_links[] = $socialMediaLinks;
    }

    /**
     * Get social_media_links
     *
     * @return Doctrine\Common\Collections\Collection $socialMediaLinks
     */
    public function getSocialMediaLinks()
    {
        return $this->social_media_links;
    }
}
namespace Lms\Entities;

/**
 *
 * @Entity
 * @Table(name="SocialMediaLink")
 */
class SocialMediaLink {

	/**
	 * @Id
	 * @Column(type="bigint")
	 * @GeneratedValue
	 */
	protected $id;

	/** @Column(type="string") */
	protected $title;

	/** @Column(type="string") */
	protected $link;

}

And when I execute:

		$sml = $this->_em->createQuery("SELECT s FROM Lms\Entities\User u JOIN u.social_media_links  AS s WHERE u.id = ?1 AND s.id = ?2")
					->setParameter(1, 1)
					->setParameter(2, 1)
					->getResult();

I get the following trace:

1) DoctrineExtensions\PHPUnit\UserTestCase::testEditSocialMediaLink
class_parents(): object or string expected

C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Mapping\ClassMetadataFactory.php:201
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Mapping\ClassMetadataFactory.php:224
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Mapping\ClassMetadataFactory.php:148
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\EntityManager.php:235
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php:220
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php:75
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\Internal\Hydration\AbstractHydrator.php:98
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\AbstractQuery.php:530
C:\xampp\htdocs\lms-user-sml-feature\system\application\libraries\Doctrine\ORM\AbstractQuery.php:360

The following data is in the database:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
	<table name="user">
		<column>id</column>
		<column>mission_Statement</column>
		<column>first_name</column>
		<column>last_name</column>
		<column>initial</column>
		<column>email</column>
		<column>company</column>
		<column>picture</column>
		<column>bio</column>
		
		<row>
			<value>1</value>
			<value>Mission Statement 1</value>
			<value>First Name 1</value>
			<value>Last Name 1</value>
			<value>IN1</value>
			<value>email1@email.com</value>
			<value>Company 1</value>
			<value>Picture 1</value>
			<value>Bio 1</value>
		</row>
	</table>
	
	<table name="socialmedialink">
		<column>id</column>
		<column>title</column>
		<column>link</column>

		<row>
			<value>1</value>
			<value>Social Media Title 1</value>
			<value>Social Media Link 1</value>
		</row>
	</table>
	
	<table name="users_socialmedialinks">
		<column>user_id</column>
		<column>socialmedialink_id</column>

		<row>
			<value>1</value>
			<value>1</value>
		</row>
	</table>
</dataset>


 Comments   
Comment by Numan S [ 30/May/10 ]

After messing around with it a little bit, the following will work:

	
		$sml = $this->_em->createQuery("SELECT u,s FROM Lms\Entities\User u JOIN u.social_media_links AS s WHERE u.id = ?1 AND s.id = ?2")
					->setParameter(1, 1)
					->setParameter(2, 1)
					->getResult();
Comment by Roman S. Borschel [ 07/Aug/10 ]

Hydration does not (yet?) support such kinds of queries where the root entity/schema name is not selected.

Comment by Benjamin Eberlei [ 15/Sep/10 ]

@roman i think this should be solved in conjunction with DDC-736 and throw an exception if the users tries to do this. Is this possible in linear time?

Comment by Benjamin Eberlei [ 28/Dec/10 ]

Fixed, a QueryException will now be thrown if attempting to select one or more identification variables without picking at least one root.





[DDC-546] New fetch mode EXTRA_LAZY for collections Created: 27/Apr/10  Updated: 02/Jan/11  Resolved: 02/Jan/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA1
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Major
Reporter: Roman S. Borschel Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 3
Labels: None

Issue Links:
Reference
relates to DDC-128 Consider adding EntityManager#link/un... Open
is referenced by DDC-80 Allow custom collections Resolved

 Description   

A new fetch mode EXTRA_LAZY for one-to-many and many-to-many associations could have the following effects on PersistentCollection methods:

  • count() : Does not initialize the collection but issues a straight SQL count query.
  • remove($key) : Does not initialize the collection but issues straight SQL instead.
  • removeElement($element) : Does not initialize the collection but issues straight SQL instead.
  • contains($element) : Does not initialize the collection but issues straight SQL instead.
  • containsKey($key) : Does not initialize the collection but issues straight SQL instead.

This mode would usually be useful for (potentially) large collections.

We need to work out concrete use-case examples and implementation proposals before implementation.

The semantics of the mentioned methods with EXTRA_LAZY need to be carefully worked out, i.e. what happens to already managed instances in case of the remove operations and stuff like that.



 Comments   
Comment by Marc Hodgins [ 07/May/10 ]

Wow, this is an excellent idea. I was just thinking how it is unfortunate that there aren't ways to manipulate large collections without resorting to DQL.

If nothing else, having access to a count() would be particularly great.

Comment by Roman S. Borschel [ 07/May/10 ]

@Marc: You might then also be interested in a related ticket: http://www.doctrine-project.org/jira/browse/DDC-547

This would basically allow you to craft special implementations that inherit from PersistentCollection that are "optimized" in some way for a specific association (i.e. write your own custom SQL query when count() is invoked). Your wrapper class is then used by Doctrine instead of the default one, thats the idea. Of course implementing such a custom collection and overriding methods needs to be done carefully to fully preserve the public API contract (PersistentCollection wrappers are supposed to be "invisible" to the user after all). So this would be an advanced feature. EXTRA_LAZY I think is a pretty easy feature, accessible for all users with no further knowledge required. It just means that the collection delays initialization even more, whereever possible, which is a good thing for large collections which you normally don't really want to load, yet it allows you to use the normal OO API of your domain model without resorting to special (DQL) queries.

Comment by Roman S. Borschel [ 07/May/10 ]

Oh, I just saw you're watching that one already sorry for the noise

Comment by Roman S. Borschel [ 19/May/10 ]

Rescheduling for beta3 as we're running out of time.

Comment by Benjamin Eberlei [ 30/Jun/10 ]

Additional features that have been requested by users:

  • Fetch entries in this collection in batches, i.e. only in 20 steps, issue a limit 0,21 and check if there is more

I don't know about the remove() and removeElement() operations, would they register with the UoW or directly execute the DELETE or UPDATE stements themselves?

Comment by Roman S. Borschel [ 07/Jul/10 ]

Pushing back to beta4.

Comment by Roman S. Borschel [ 12/Jul/10 ]

Moved to 2.1 due to lack of time for larger new stuff for 2.0.

Comment by Benjamin Eberlei [ 04/Dec/10 ]

https://github.com/doctrine/doctrine2/tree/DDC-546 first prototype implementation with tests.

Missing:

  • XML and YAML Mapping support.
  • Contains() support.
  • RemoveElement() support

Necessary for later scheduling (only make sense when persisting keys):

  • ContainsKey() support
  • RemoveKey() support
Comment by Benjamin Eberlei [ 29/Dec/10 ]

I updated the branch to include XML, YAML support, refactored a little bit and added contains() support.

The RemoveElement() support should be put into its own ticket that relates to the EntityManager#link() / EntityManager#unlink() functionality.

Comment by Benjamin Eberlei [ 02/Jan/11 ]

Implemented

Comment by Benjamin Eberlei [ 02/Jan/11 ]

Usage would be inside a @OneToMany or @ManyToMany definition set

Annotations/XML:

fetch="EXTRA_LAZY"

YAML:

fetch: EXTRA_LAZY




[DDC-250] ArrayCollection Key Column @indexBy Created: 12/Jan/10  Updated: 29/Dec/13  Resolved: 05/Feb/11

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: None
Fix Version/s: 2.1
Security Level: All

Type: New Feature Priority: Minor
Reporter: Michael Ridgway Assignee: Benjamin Eberlei
Resolution: Fixed Votes: