[DDC-3234] Empty properties when filtering collections Created: 30/Jul/14  Updated: 20/Aug/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.5, 2.4.2
Fix Version/s: 2.x
Security Level: All

Type: Bug Priority: Major
Reporter: Diogo Domanski de Souza Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: Collection, Criteria, orm
Environment:

PHP 5.5.9, Nginx 1.4.6, PHP FPM, Zend Framework 2.3.1, Linux Ubuntu 14.04



 Description   

I'm facing some troubles when filtering an entity association (ArrayCollection) by using Criteria.

The scenario is the following: I have 3 entities:

User.php
<?php

namespace Entity;

use Doctrine\ORM\Mapping as ORM;
use \Doctrine\Common\Collections\Criteria;
use Zend\Stdlib\Hydrator;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="Entity\UserRepository")
 * @ORM\HasLifecycleCallbacks
 * @author domanski
 */
class User implements \Serializable {
	/**
	 *
	 * @ORM\Id
	 * @ORM\Column(name="id", type="integer", nullable=false)
	 * @ORM\GeneratedValue(strategy="AUTO")
	 * @var integer
	 */
	private $id;

	/**
	 * @ORM\Column(name="delete_date", type="datetime")
	 * @var \DateTime
	 */
	private $deleteDate;
	
	public function __construct(array $options = array()) {
		if (!empty($options))
			$this->hydrate($options);
	}

	public function hydrate(array $options = array(), \Doctrine\ORM\EntityManager $em = null) {
		$hydrator = new Hydrator\ClassMethods();
		$hydrator->hydrate($options, $this);
	}

	/**
	 * 
	 * @return int
	 */
	public function getId() {
		return $this->id;
	}

	/**
	 * 
	 * @param int $id
	 * @return \Entity\User
	 */
	public function setId($id) {
		$this->id = $id;
		return $this;
	}

	/**
	 * 
	 * @return \DateTime
	 */
	public function getDeleteDate() {
		return $this->deleteDate;
	}

	/**
	 * @param \DateTime|null $deleteDate
	 * @return \Entity\User
	 */
	public function setDeleteDate($deleteDate = null) {
		$this->deleteDate = $deleteDate;
		return $this;
	}

	/**
	 * 
	 * @return array
	 */
	public function toArray() {
		$result = array(
			'id' => $this->getId(),
			'delete_date' => $this->getDeleteDate()
		);

		return $result;
	}

}
FieldWorker.php
<?php

namespace Entity;

use Doctrine\ORM\Mapping as ORM;
use \Doctrine\Common\Collections\Criteria;

use Zend\Stdlib\Hydrator;

/**
 * Description of FieldWorker
 *
 * @ORM\Entity(repositoryClass="Entity\FieldWorkerRepository")
 * @ORM\Table(name="field_worker")
 * @ORM\HasLifecycleCallbacks
 * @author domanski
 */
class FieldWorker {
	
	/**
	 * This attribute must exist so the inverse join with any other entity can work
	 * 
	 * @ORM\Id
	 * @ORM\Column(type="integer", name="user_id")
	 * @var string
	 */
	protected $id;
	
	/**
	 * 
	 * @ORM\OneToOne(targetEntity="Entity\User")
	 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
	 * @var \Entity\User
	 */
	protected $user;
	
	public function __construct($options = array()) {		
		if(!empty($options))
			$this->hydrate($options);
	}
	
	public function hydrate(array $options = array(), \Doctrine\ORM\EntityManager $em = null) {
		if(!empty($em)) {
			// user
			if(isset($options['user']))
				$options['user'] = $em->getReference('Entity\User', $options['user']);
			else if(isset($options['user_id']))
				$options['user'] = $em->getReference('Entity\User', $options['user_id']);
						
		}
		
		$hydrator = new Hydrator\ClassMethods();
		$hydrator->hydrate($options, $this);
	}

	/**
	 * 
	 * @return \Entity\User
	 */
	public function getUser() {
		return $this->user;
	}

	/**
	 * 
	 * @param \Entity\User $user
	 * @return \Entity\FieldWorker
	 */
	public function setUser(\Entity\User $user) {
		$this->user = $user;
		$this->id = $user->getId();
		return $this;
	}
	
	/**
	 * 
	 * @return array
	 */
	public function toArray() {
		return $this->getUser()->toArray();
	}
}
Stage.php
<?php

namespace Obra\Entity;

use Doctrine\ORM\Mapping as ORM;
use Zend\Stdlib\Hydrator;
use Doctrine\Common\Collections\Criteria;

/**
 * Description of Stage
 *
 * @ORM\Table(name="stage")
 * @ORM\Entity(repositoryClass="Entity\StageRepository")
 * @ORM\HasLifecycleCallbacks
 * @author domanski
 */
class Stage {

	/**
	 *
	 * @ORM\Id
	 * @ORM\Column(name="id", type="integer", nullable=false)
	 * @ORM\GeneratedValue(strategy="AUTO")
	 * @var integer
	 */
	private $id;

	/**
	 * @ORM\ManyToMany(targetEntity="Entity\FieldWorker")
	 * @ORM\JoinTable(name="stage_field_worker",
	 * 		joinColumns={@ORM\JoinColumn(name="stage_id", referencedColumnName="id")},
	 * 		inverseJoinColumns={@ORM\JoinColumn(name="field_worker_id", referencedColumnName="user_id")}
	 * 	)
	 * @var \Doctrine\Common\Collections\ArrayCollection
	 */
	private $fieldWorkers;

	public function __construct(array $options = array()) {
		$this->fieldWorkers = new \Doctrine\Common\Collections\ArrayCollection();

		if (!empty($options))
			$this->hydrate($options);
	}

	public function hydrate(array $options = array(), \Doctrine\ORM\EntityManager $em = null) {
		$hydrator = new Hydrator\ClassMethods();
		$hydrator->hydrate($options, $this);
	}

	/**
	 * 
	 * @return int
	 */
	public function getId() {
		return $this->id;
	}

	/**
	 * 
	 * @param int $id
	 * @return \Entity\Stage
	 */
	public function setId($id) {
		$this->id = $id;
		return $this;
	}

	/**
	 * 
	 * @return \Doctrine\Common\Collections\ArrayCollection
	 */
	public function getFieldWorkers() {
		$criteria = Criteria::create()
				->where(Criteria::expr()->isNull("user.deleteDate"))
				->orderBy(array("user.name" => Criteria::ASC));

		return $this->fieldWorkers->matching($criteria);
	}

	/**
	 * 
	 * @return \Entity\Stage
	 */
	public function clearFieldWorkers() {
		$this->fieldWorkers->clear();
		return $this;
	}

	/**
	 * 
	 * @param \Entity\FieldWorker $fieldWorker
	 * @return \Entity\Stage
	 */
	public function addFiscal(\Entity\FieldWorker $fieldWorker) {
		$this->fieldWorkers->add($fieldWorker);
		return $this;
	}

	/**
	 * 
	 * @return array
	 */
	public function toArray() {
		$result = array(
			"id" => $this->getId(),
			"field_workers" => array()
		);

		foreach ($this->getFieldWorkers() as $fieldWorker) {
			$result['field_workers'][] = $fieldWorker->toArray();
		}

		return $result;
	}
}

The problem is that whenever the Stage::getFieldWorkers() method is invoked, the list of associated field workers is returned correctly, however if I try to retrieve the respective user of any field worker, it is NULL.

For example:

$stageEntity = $em->getRerefence('Entity\Stage', 1);
$fieldWorkers = $stageEntity->getFieldWorkers();

foreach($fieldWorkers as $fieldWorker) {
   $userId = $fieldWorker->getUser()->getId(); // This throws an error message saying that the result of getUser() is NULL
}

Another example would be if I try to call $stageEntity->toArray() (because it does the same thing as show above).

The database tables are as following:

Database tables creation
CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `delete_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `field_worker` (
  `user_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`user_id`),
  CONSTRAINT `fk_field_worker_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `stage` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `stage_field_worker` (
  `stage_id` int(10) unsigned NOT NULL,
  `field_worker_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`stage_id`,`field_worker_id`),
  KEY `fk_stage_field_worker_stage_idx` (`stage_id`),
  KEY `fk_stage_field_worker_field_worker_idx` (`field_worker_id`),
  CONSTRAINT `fk_stage_field_worker_field_worker` FOREIGN KEY (`field_worker_id`) REFERENCES `field_worker` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_stage_field_worker_stage` FOREIGN KEY (`stage_id`) REFERENCES `stage` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` SET `id` = 1;
INSERT INTO `field_worker` SET `user_id` = 1;
INSERT INTO `stage` SET `id` = 1;
INSERT INTO `stage_field_worker` SET `stage_id` = 1, `field_worker_id` = 1;

After hours trying to understand what was wrong, I decided to make a test and modify the Stage::getFieldWorkers() method by removing the filtering Criteria:

public function getFieldWorkers() {
    return $this->fieldWorkers;
}

By simply doing that, the getUser() method started to return an entity of type User (as expected).

I am not a Doctrine ORM expert, but there seems to be something wrong with ArrayCollection filtering (matching() method)



 Comments   
Comment by Diogo Domanski de Souza [ 30/Jul/14 ]

The same problem occurs with QueryBuilder. For example:

StageRepository.php
<?php

namespace Entity;

use Doctrine\ORM\EntityRepository;

/**
 * Description of StageRepository
 *
 * @author domanski
 */
class StageRepository extends EntityRepository 
{

	public function findByFieldWorkerId($fieldWorkerId) {
		$qb = $this->getEntityManager()->createQueryBuilder()
			->select('s')
			->from('Entity\Stage', 's')
			->innerJoin('s.fieldWorkers', 'f')
			->innerJoin('f.user', 'u', \Doctrine\ORM\Query\Expr\Join::WITH, "u.deleteDate IS NULL AND u.id = :field_worker_id")
				->setParameter('field_worker_id', $fieldWorkerId);

		return $qb->getQuery()->getResult();
	 }
}

If I try to iterate over the result of StageRepository::findByFieldWorkerId() and call toArray() of any element, I get the same error. I've even tried to remove the inner join with User entity from query:

	public function findByFieldWorkerId($fieldWorkerId) {
		$qb = $this->getEntityManager()->createQueryBuilder()
			->select('s')
			->from('Entity\Stage', 's')
			->innerJoin('s.fieldWorkers', 'f');

		return $qb->getQuery()->getResult();
	 }
Comment by Marco Pivetta [ 30/Jul/14 ]

I suspect that something is wrong in your mappings then...

Comment by Diogo Domanski de Souza [ 31/Jul/14 ]

Hi Marco,

The mappings are shown above. The only thing I did was to omit some entities/tables properties/columns that don't have to see with the associations - except the field worker (table and Entity) and stage_field_worker table, that are fully presented.

Maybe is important to notice that the field_worker table has only one column (user_id) that is primary key and foreign key (referencing user.id).

Thanks for you support

Comment by Marco Pivetta [ 31/Jul/14 ]

Diogo Domanski de Souza we can't debug this as it is. We'd need a functional test case to be added to https://github.com/doctrine/doctrine2/tree/0650bb954f5e8d05776f99abd04c81948413299f/tests/Doctrine/Tests/ORM/Functional/Ticket first, in order to see the failure

Comment by Diogo Domanski de Souza [ 31/Jul/14 ]

Marco Pivetta is there any documentation (tutorial, instructions, guide, etc) that I can use to learn how to write the functional test cases that I need?

Comment by Marco Pivetta [ 31/Jul/14 ]

Diogo Domanski de Souza you need to look at the existing ones.

For running the test suite:

git clone git@github.com:doctrine/doctrine2.git
cd doctrine2 
curl -s https://getcomposer.org/installer | php --
./composer.phar install
./vendor/bin/phpunit
Comment by Diogo Domanski de Souza [ 20/Aug/14 ]

I solved the problem by removing the property $id from FieldWorker entity and add annotation @ORM\Id to $user property (in this same entity).

I didn't understand why the previous definition of FieldWorker entity was not working. I have another similar relationship scenario, between 3 different entities, and the error does not occur.

Thanks to all for the support





[DDC-2570] Doctrine CLI Tools - Clear All Cache Created: 24/Jul/13  Updated: 08/Feb/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM, Tools
Affects Version/s: 2.3.4
Fix Version/s: 2.x, 2.5

Type: Improvement Priority: Minor
Reporter: Frederick Marcoux Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: Cli, cache, orm


 Description   

It would be nice to be able to clear all cache one shot instead of clearing them one after one...

Like this:

root$ ./doctrine orm:clear-cache:all

Instead of:

root$ ./doctrine orm:clear-cache:metadata
root$ ./doctrine orm:clear-cache:result
root$ ./doctrine orm:clear-cache:query






[DDC-1963] Remove by-ref access to changeset in lifecycle event args Created: 31/Jul/12  Updated: 16/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x, 2.5
Security Level: All

Type: Improvement Priority: Major
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Unresolved Votes: 0
Labels: None


 Description   

UoW currently passes computed changesets to lifecycle event args byref. This has to be changed to force users to use UoW public API to modify changesets instead.






[DDC-1852] Doctrine\ORM\Tools\SchemaValidator should check validity of lifecycle callbacks Created: 04/Jun/12  Updated: 16/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.x, 2.5
Security Level: All

Type: Improvement Priority: Major
Reporter: Marco Pivetta Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The schema validator should analyze mapped lifecycle callbacks and:

a) if some lifecycle callbacks were defined, but no @HasLifecycleCallbacks annotation/mapping was set, warn the user
b) if some lifecycle callbacks were defined, but methods are not public, warn the user



 Comments   
Comment by Marco Pivetta [ 04/Jun/12 ]

Existing PR at https://github.com/doctrine/doctrine2/pull/361





[DDC-1729] Translate queries into graphs of value objects (instead of array hydration?) Created: 27/Mar/12  Updated: 09/Jun/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In decoupled applications the model layer returns "data-transfer-objects" through the boundary into the controller/view layer. It would make sense to have Doctrine directly generate any data-transfer/value-object from native and dql queries.



 Comments   
Comment by Benjamin Eberlei [ 09/Jun/12 ]

Example:

$dql = "SELECT new CustomerAddressView(c.id, c.name, a.id, a.street, a.number, a.city, a.code)
             FROM Customer c INNER JOIN c.address a WHERE c.id = ?1";

This supersedes DDC-1819.

1. One additional property in ResultSetMapping => $viewModelClass?
2. Changes to Parser (new ... syntax)
3. Changes to sQL Walker?
4. Changes to Hydration (Only object hydration!)





[DDC-1543] Support for Mapping Files on Traits Created: 17/Dec/11  Updated: 17/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

With PHP 5.4 and traits coming we should find a way where you can add xml and yml configurations for a trait and upon loading an entity X, it also loads the trait configuration of this entity.






[DDC-1530] HIDDEN values cannot be used in WhereClause Created: 12/Dec/11  Updated: 25/Jan/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: Git Master
Fix Version/s: 2.x
Security Level: All

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


 Description   
SELECT  u, u.name AS HIDDEN n FROM User u WHERE n = ?1

Is broken. Error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sclr16' in 'where clause

On a query like:

SELECT s0_.id AS id0, s0_.a AS a1, s0_.b AS b2, s0_.c AS c3, s0_.d AS d4, s0_.e AS e5, s0_.f AS f6, s0_.g AS g7, s0_.h AS h8, s0_.i AS i9, s0_.j AS j10, s0_.k AS k11, s0_.l AS l12, s0_.m AS m13, s0_.n AS n14, s0_.o AS o15, 123456789 AS sclr16, s0_.p AS p17 FROM myEntity s0_ WHERE s0_.a = 1 AND sclr16 <= ? ORDER BY sclr16 ASC 


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

Updating fix version

Comment by Christian Raue [ 09/Jan/12 ]

It occurs even if the value is not HIDDEN.

Comment by Benjamin Eberlei [ 10/Jan/12 ]

@Christian this sounds like a completly different error, please explain why you think this belongs here or open a new ticket.

Comment by Christian Raue [ 10/Jan/12 ]

Benjamin: Because I get exactly the same error message regardless of using HIDDEN. So HIDDEN doesn't seem to be liable here.

Comment by Benjamin Eberlei [ 10/Jan/12 ]

Can you paste your DQL and SQL?

Comment by Christian Raue [ 10/Jan/12 ]

Code:

$queryBuilder
	->select('myEntity, 123456789 AS distance')
	->where('distance <= 10')
;

DQL:

SELECT myEntity, 123456789 AS distance FROM MyCompany\MyBundle\Entity\MyEntity myEntity WHERE distance <= 10

SQL:

SELECT s0_.id AS id0, s0_.a AS a1, s0_.b AS b2, s0_.c AS c3, s0_.d AS d4, s0_.e AS e5, s0_.f AS f6, s0_.g AS g7, s0_.h AS h8, s0_.i AS i9, s0_.j AS j10, s0_.k AS k11, s0_.l AS l12, s0_.m AS m13, s0_.n AS n14, s0_.o AS o15, 123456789 AS sclr16, s0_.p AS p17 FROM myEntity s0_ WHERE sclr16 <= 10
Comment by Benjamin Eberlei [ 11/Jan/12 ]

That is expected behavior, ANSI SQL defines SELECT to be evaluated AFTER WHERE.

SELECT 1234 AS foo FROM `test` HAVING foo = 1234

DQL has a HAVING clause as well, not sure it works without the group by. Please try.

Comment by Christian Raue [ 21/Jan/12 ]

So we might just close this issue then?

Comment by Benjamin Eberlei [ 25/Jan/12 ]

Its not a bug, just the error message is supposed to be improved (if possible) in a cheap way.





[DDC-1450] UnitOfWork Transaction Rollback Support Created: 24/Oct/11  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

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


 Description   

The UnitOfWork does not handle the case very well where a rollback is necessary. Can this be optimized?



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

Updating fix version





[DDC-1445] Improve error messages Created: 22/Oct/11  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

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


 Description   

Error messages throughout ClassMetadata validation and UnitOfWork cycles can be significantly improved.

Work is being done on: https://github.com/doctrine/doctrine2/tree/ImproveErrorMessages



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

Updating fix version





[DDC-1415] EventListener delegate on entity basis Created: 11/Oct/11  Updated: 20/Dec/11

Status: Reopened
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


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

Removed from master, as i dont like the api at all

Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version





[DDC-1393] Skipping tables or columns in database driver or SchemaTool Created: 24/Sep/11  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.1.1, Git Master
Fix Version/s: 2.x
Security Level: All

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


 Description   

There should be a sane way to skip sources of errors in SchemaTool and the DatabaseDriver.



 Comments   
Comment by Benjamin Eberlei [ 24/Sep/11 ]

Idea:

Develop a datastructure of sorts that allows saving information about skipping tables and columns therein when reverse engeneering.

Comment by Guilherme Blanco [ 09/Dec/11 ]

This is not possible unless you take advantage of Topological Sorting to map class dependencies like we do inside of UnitOfWork AFTER creating the ClassMetadata.

The necessity of having this is mandatory because we can never skip classes that have associations to other ones though FK.
You may try that, but it doesn't compensate the effort. I'd rather mark this bug as won't fix, but I'm leaving for you do that. =)

Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version





[DDC-1373] Map file with specific class Created: 13/Sep/11  Updated: 14/Feb/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.1.1
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Minor
Reporter: Thomas Tourlourat - Armetiz Assignee: Fabio B. Silva
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Debian LAMP - PHP5.3 - Apache 2



 Description   

Hi there,
AbsractFileDriver is using the filename to know the managed class.

It's a cool feature because it's allow loading on-demand.
The problem is, that the filename must be the name of the Class.

It should be great to be able to manually map XML/YAML File description to a Class, like :
$drivers->addMappingFile ( array ( "filename" => "class", "filename2" => "class2") );

This feature is simple to implement, just add a new array inside AbsractFileDriver to know the mapping.
When using the current method with addPaths, parse the folder to get traditional XML/YAML file where filename corresponding to classname and add it to the mapping array.

AbsractFileDriver->getAllClassNames () just return value of mapping array.
The mapping array is store inside cache.

With this new feature, it allow developers to create a pretty folder that contains entities mapping.

Armetiz.



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

Updating fix version





[DDC-1370] preInsert, postInsert, prePersist, postPersist, preUpdate, postUpdate code and documentation of events Created: 09/Sep/11  Updated: 26/Feb/14

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Minor
Reporter: Guilherme Blanco Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Currently we have a set of Lifecycle events, but they seem to be misleading both in actual implementation and documentation.

One good example is prePersist and postPersist, which is only fired when you're creating new entities. It should be renamed to preInsert and postInsert.
As of preUpdate and postUpdate, they seem quite valid.

But if we rename prePersist and postPersist to (pre|post)Insert, we may have a situation where you wanna cover both insert and update.
For this, (pre|post)Persist should be reinstated, but acting differently from what it does currently.



 Comments   
Comment by Rafael Dohms [ 09/Sep/11 ]

Also, documentation for post* methods is broken at the website:

"Changes in here are not relevant to the persistence in the database, but you can use this events to"

It cuts off in mid-sentence.

Comment by Guilherme Blanco [ 09/Dec/11 ]

RDohms, this paragraph was already sorted out.

The actual ticket is still valid here.

Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version

Comment by Matt McNeill [ 26/Feb/14 ]

Commenting here to say that this caused a lot of headaches for our project until we got it sorted out what these events really do.

The problem is that the term 'persist' is ambiguous - it means both persist and update in the context of the persist() function call, but only means INSERT in the context of the event system.





[DDC-1320] Ship Immutable date time with Doctrine Common, use in ORM - Should implement __toString() Created: 06/Aug/11  Updated: 31/Oct/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

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

Issue Links:
Dependency
depends on DDC-1316 Insert statement for joined subclass ... Resolved

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

Has to be pushed back as immutable date time cannot be implemented in userland that well.





[DDC-1308] Add cache for transient information and invalidation for ClassMetadata Created: 31/Jul/11  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

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


 Description   

Two different things have to be improved in the caching:

1. The information isTransient() has to be moved to the ClassMetadataFactory and cached there.
2. The information getAllClassMetadataNames() can be cached
3. A debug/development mode should be introduced, leading to filemtime caching and checks so that you can use ApcCache and such in development.



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

Updating fix version





[DDC-1264] Add more math related DQL funcs (trig, round, stuff?) Created: 09/Jul/11  Updated: 09/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None





[DDC-1262] Have proxies copy docblocks aswell Created: 09/Jul/11  Updated: 09/Jul/11

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

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


 Description   

Whenever a Proxy is generated it does not copy the docblocks.

This means when you do something like "$refl = new ReflectionObject($proxy)" you might be in trouble.

However if we add docblocks then we have to make sure that proxies do not magically appear as entities by throwing an exception in the AnnotationDriver.






[DDC-1229] generate entity interactive dialog: id column Created: 27/Jun/11  Updated: 28/Jun/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: David Buchmann Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

according to Stof, this bug https://github.com/sensio/SensioGeneratorBundle/issues/21 comes from the doctrine tools implementation:

in the dialog, i first specified that i want a field id of type integer. the result was

[Doctrine\ORM\Mapping\MappingException]

Duplicate definition of column 'id' on entity 'Liip\DemoBundle\Entity\Event' in a field or discriminator column mapping.

and no file was created.

The dialog should tell me i can not create a field named id. (Or better ask first if i want my id column named id or something else.)

It would be nice if it would write some file even if its not valid, with a warning on top. As it is, i lost all my work of specifying fields. (Luckily was just playing around)



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

not a bug, its a feature (though a dumb one). Improvement in a next version.





[DDC-1219] Remove dependancy on Collection interface in Domain Objects Created: 21/Jun/11  Updated: 04/Jul/11

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

Type: Improvement Priority: Major
Reporter: André R. Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Short: This issue is all about being able to use doctrine with naked domain objects without any use of doctrine classes.
I 'm not talking about PersistentCollection here, fully aware of that being tied into Doctrine, but those are injected, this is all about code dependency on ArrayCollection.

Seems like some of the UnitOfWork code is cable of handling other types of arrays, like:

    // If $actualData[$name] is not a Collection then use an ArrayCollection.
    if ( ! $actualData[$name] instanceof Collection) {
        $actualData[$name] = new ArrayCollection($actualData[$name]);
    }

But in __cascade* functions this is not the case in all but two:

    if ($relatedEntities instanceof Collection) {
        if ($relatedEntities instanceof PersistentCollection) {
            // Unwrap so that foreach() does not initialize

2 however have:

    if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
        if ($relatedEntities instanceof PersistentCollection) {
            // Unwrap so that foreach() does not initialize

Would it be an idea to do "instanceof Traversable" instead of " instanceof Collection"?



 Comments   
Comment by André R. [ 21/Jun/11 ]

Note: If the fist code block is always performed before the last 2 blocks then there is no issue here, just a need to make it more clear in Doc that this is possible but that you should not rely custom implementation as PersistentCollection will be injected when loaded from db.





[DDC-1200] Derived Id Generator Created: 09/Jun/11  Updated: 09/Nov/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 5
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-1315 ORM\Id\AssignedGenerator doesn't work... Resolved

 Description   

For usage with the foreign key as primary key features described in DDC-117 a derived id generator would be tons of useful. It is essentially a post generate id generator (sort of late pre insert though) assigned generator.



 Comments   
Comment by Daniel Lima [ 09/Nov/11 ]

When this will be fixed?

I think this is related to http://groups.google.com/group/doctrine-user/browse_thread/thread/7e1cfa9c4c99af31





[DDC-1178] Have access to "original" metadata in events subscribed to loadClassMetadata Created: 27/May/11  Updated: 27/May/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.x
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Miha Vrhovnik Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

If you subscribe to loadClassMetadata you will usually modify the metadata for some classes.
The problem is, that that data has to be loaded from somewhere. But later down the chain you can't get to it. Now data specific to what you need in your loadClassMetadata would ideally reside in the same location.
If we take for example a file, than all data for a specific entity is in the same file.

My proposal would be to add function get(Original|Raw)MappingData into interface Doctrine\ORM\Mapping\Driver\Driver which would either return raw data or data in a object specific for that Driver or null if it doesn't make sense for that driver. Please note, that when loading from e.g XmlDriver we should return simplexmlnode or dom node as loadClassMetadata should be in its own namespace and not pollute the Doctrine one.



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

Sounds logic, each driver would expect NULL or data (wrapped specifically for the driver used)





[DDC-947] Optmize Code-Generation Strategies Created: 24/Dec/10  Updated: 29/Mar/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should optimize code-generation somehow.



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

Descheduled to 2.x





[DDC-896] Use PDepend for Code-Generation Created: 27/Nov/10  Updated: 27/Nov/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Our current code-generation tool has many shortcomings and due to its hard to test nature also many (known and unknown) bugs, as well as high maintenance.

Since people are overusing this tool and I am sort of annoyed by how much time goes into this we should rewrite this in a two-step procedure:

1. Move code into Common so we can share it between ORM, Mongo and CouchDB.
2. Use PDepend to read an entities source file (it generates an AST) and modify the AST with the required changes.

This gives us the advantage of having to maintaining less code for this stuff.






[DDC-838] SchemaTool - ignores the attribute uniq in relations Created: 13/Oct/10  Updated: 29/Oct/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: Tools
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Minor
Reporter: gektor Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Ubuntu, PHP 5.3.2, MySQL



 Description   
Mapper
<entity name="Default_Model_Test" table="test">
  <id name="id" type="integer" column="id">
    <generator strategy="AUTO"/>
  </id>
  <field name="blabla" column="blabla" type="boolean"/>
  <one-to-one field="user" target-entity="Users_Model_User">
    <join-column name="users_id" referenced-column-name="id" on-delete="CASCADE" on-update="CASCADE" unique="false" />
  </one-to-one>
</entity>
SQL
CREATE TABLE test (id INT AUTO_INCREMENT NOT NULL, users_id INT DEFAULT NULL, blabla TINYINT(1) NOT NULL, UNIQUE INDEX test_users_id_uniq (users_id), PRIMARY KEY(id)) ENGINE = InnoDB;
ALTER TABLE test ADD FOREIGN KEY (users_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE;

Actual:
UNIQUE INDEX test_users_id_uniq (users_id)

Expected:
INDEX test_users_id (users_id)



 Comments   
Comment by Benjamin Eberlei [ 14/Oct/10 ]

Verified, i just don't understand why you are using a one-to-one relation and then "deactivate" the database constraint for this. You could easily use Many-To-One

Comment by gektor [ 14/Oct/10 ]

You are right. It's not a bug, it's feature.

Comment by Benjamin Eberlei [ 29/Oct/10 ]

This might still be a good improvement to allow the flexibility, but its not a bug. Updating to "Minor Improvmenet for 2.x"





[DDC-810] Issue with detaching entities and updating when using change notification Created: 17/Sep/10  Updated: 04/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-BETA4
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Jonathan H. Wage Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File DDC810Test.php    

 Description   

More information coming soon. Attaching a test case



 Comments   
Comment by Benjamin Eberlei [ 20/Sep/10 ]

From reading the issue i know what the bug is, indeed this sucks.

Comment by Roman S. Borschel [ 28/Sep/10 ]

@Jon: Any more information coming?

@Benjamin: Can you summarize the essence of the issue shortly?

Comment by Benjamin Eberlei [ 29/Sep/10 ]

@Roman: The UnitOfWork (may) still be pushed as a listener into that entity, and still recieve noticies of update. Which may throw notices because the oid hashes are removed everywhere. Additionally you cant serialize the thing because you still got the UoW inside there.

Comment by Jonathan H. Wage [ 04/Oct/10 ]

I don't have anymore information currently. The issue was relayed to me. I will try and find some more information and report back.

Comment by Benjamin Eberlei [ 03/Apr/11 ]

There is no way to "fix" this issue, i am turning it into a feature request. There needs to be a "postDetach" event that is triggered where the developer can detach the change notification objects.





[DDC-763] Cascade merge on associated entities can insert too many rows through "Persistence by Reachability" Created: 23/Aug/10  Updated: 04/Jul/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Dave Keen Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File 0149-DDC-763.patch     File DDC763Test.php     File multipleaddmerge.diff    

 Description   

I think that the UnitOfWork needs to maintain a map of spl_object_hash($newEntity)->$managedEntity for entities that were persisted via reachability during a merge. doMerge should then only call persistNew if the original entity has not already been persisted (if it has already been persisted it should merge the managed entity from the map). The map should be maintained until a flush() or until the UnitOfWork is cleared. The reasoning is as follows.

Imagine we have a simple doctor object with no associations:

$doctor = new Doctor();
$em->persist($doctor);
$em->persist($doctor);
$em->flush();

After the first persist() $doctor is MANAGED so the second persist has no effect and this results in a single Doctor row.

If we do the same thing using merge and persistence by reachability:

$doctor = new Doctor();
$em->merge($doctor);
$em->merge($doctor);
$em->flush();

we get 2 Doctor rows being added.

Obviously in this particular case we should use the return value from the first merge() as the parameter of the second merge which would give correct behaviour.

However, now imagine one Doctor has many Patients and many Patients have one Doctor, all the associations have cascade merge enabled, and further assume that $d1 (Doctor id=1) is already in the database. We now attempt to create two patients and assign them to the existing doctor:

$d1= new Doctor(); $d1->id = 1; // This is a DETACHED entity

$p1 = new Patient();
$p2 = new Patient();

$d1->patients->add($p1); $p1->doctor = $d1;
$d1->patients->add($p2); $p2->doctor = $d1;

$em->merge($p1);
$em->merge($p2);

$em->flush();

This actually results in 4 rows being added to the 'patients' table instead of 2, I think because $p1 and $p2 are getting persisted both as the root objects and then again from the patient->doctor->patients array. Since the cascade merging happens internally we can't replace the array contents with the managed return values without walking through the object graph (in which case there is no point in using cascade merge in the first place). Maintaining a map in UnitOfWork will allow doMerge to ensure it doesn't persist the same entities twice.

I'm not sure, but this might be relevant for cascade persist too.

P.S. Another bug report on this can be found at http://code.google.com/p/flextrine2/issues/detail?id=32 (it basically says the same thing with different entities).



 Comments   
Comment by Benjamin Eberlei [ 29/Aug/10 ]

@Roman A possible fix for this in my opinion is another map in UnitOfWork $mergedEntities = array(); and a patch like this:

diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 242d84b..1d0d8b3 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -1340,6 +1340,10 @@ class UnitOfWork implements PropertyChangedListener
             return; // Prevent infinite recursion
         }
 
+        if (isset($this->mergedEntities[$oid])) {
+            return $this->mergedEntities[$oid];
+        }
+
         $visited[$oid] = $entity; // mark visited
 
         $class = $this->em->getClassMetadata(get_class($entity));
@@ -1468,6 +1472,8 @@ class UnitOfWork implements PropertyChangedListener
 
         $this->cascadeMerge($entity, $managedCopy, $visited);
 
+        $this->mergedEntities[$oid] = $managedCopy;
+
         return $managedCopy;
     }
Comment by Dave Keen [ 29/Aug/10 ]

I have tested this patch with my application and it fixes the problem in all my relevant test cases apart from one. The test case that's failing is one that persists a bi-directional many to many relationship, so the associations interweave with each other (if you know what I mean).

I wonder if perhaps doMerge need to continue cascading even if it finds an item in $this->mergedEntities

This is the Flextrine code that fails - it results in no entries in movie_artist. This might also be related to DDC-758?

m1 = new Movie();
m1.title = "Movie 1";

m2 = new Movie();
m2.title = "Movie 2";

a1 = new Artist();
a1.name = "Artist 1";

a2 = new Artist();
a2.name = "Artist 2";

m1.artists.addItem(a1); a1.movies.addItem(m1);
m1.artists.addItem(a2); a2.movies.addItem(m1);

m2.artists.addItem(a1); a1.movies.addItem(m2);
m2.artists.addItem(a2); a2.movies.addItem(m2);

// These translate to cascade merges on the server
em.persist(m1);
em.persist(m2);
em.persist(a1);
em.persist(a2);

// Now flush
em.flush();

Comment by Dave Keen [ 29/Aug/10 ]

P.S. This test passes if I translate em.persist() to $em->persist() (not cascading) on the server instead of translating it to a cascade merge; not sure if that helps

Comment by Roman S. Borschel [ 30/Aug/10 ]

I'd really like to avoid introducing an additional instance variable just to solve this issue but I did not find the time yet to really look into it.

Does someone have a unit test for this already and can attach it to the issue?

Comment by Roman S. Borschel [ 31/Aug/10 ]

Rescheduling for RC1.

Comment by Dave Keen [ 13/Sep/10 ]

Here is a functional test case containing three tests:

testMultiMerge tests basic merging of two new entities, checking that only a single entity ends up in the database. This passes with Benjamin's patch.

testMultiCascadeMerge tests the more complex case of merging a OneToMany association. This also passes with Benjamin's patch.

testManyToManyPersistByReachability tests the ManyToMany case described above and this fails with Benjamin's patch, probably because doMerge doesn't cascade down entities that it has already merged and some ManyToMany associations are being ignored. Its a bit hard to be certain what is causing this as even without Benjamin's patch this test would fail due to DDC-758.

Comment by Benjamin Eberlei [ 15/Sep/10 ]

@Roman i thought about this issue, its not possible without that additional map of merged entities. There is no way we can get that information from other sources.

Problem is rather that the use-case probably only applies in mass-merging scenarios and client-server serialization.

Comment by Dave Keen [ 21/Sep/10 ]

Added another failing test case - adding the same entity from different ends of a many to many bi-directional association to check that there isn't an integrity constraint violation caused by Doctrine trying to add the same row twice.

Comment by Dave Keen [ 21/Sep/10 ]

Attached a patch for this issue.

Comment by Benjamin Eberlei [ 22/Sep/10 ]

can you comment why all the additionall stuff is necessary compared to my patch?

Comment by Dave Keen [ 22/Sep/10 ]

It fixes the two additional test cases - testManyToManyPersistByReachability and testManyToManyDuplicatePersistByReachability.

testManyToManyPersistByReachability was failing with your original patch because there are ManyToMany cases where an entity may have already been merged, but its still necessary to add it to an association and continue to cascade. Running the following with the original patch will miss out some of the associations.

$m1 = new Movie();
$m1->title = "Movie 1";

$m2 = new Movie();
$m2->title = "Movie 2";

$a1 = new Artist();
$a1->name = "Artist 1";

$a2 = new Artist();
$a2->name = "Artist 2";

$m1->artists->add($a1); $a1->movies->add($m1);
$m1->artists->add($a2); $a2->movies->add($m1);
$m2->artists->add($a1); $a1->movies->add($m2);
$m2->artists->add($a2); $a2->movies->add($m2);

$em->merge($a1);
$em->merge($a2);
$em->flush();

The other change in my patch is to protect against this case. It ensures that the following code doesn't add the same entity twice to a collection.

$em->merge($m1);
$em->merge($m2);
$em->merge($a2);
$em->merge($a2);
$em->flush();
Comment by Benjamin Eberlei [ 31/Oct/10 ]

I am not sure if the issue here is rather multiple calls to merge that contain different parts of the same object-graph.

There should be a very simple fix for this, call ->clear() after each merge.

I am not sure if this patch drags us into a blackhole of issues with merging.

Comment by Dave Keen [ 31/Oct/10 ]

Calling ->clear() and ->flush() after each merge is a workaround for the simple case, but unless I am misunderstanding I don't think its a solution for cases where the merging is happening automatically in cascadeMerge. I've actually encountered this issue in another project and scenario to do with creating REST APIs and merging JSON objects into entities, and applying the patch fixed it so a) I think this issue might be a more common that we first thought and b) the patch basically seems to work (plus it doesn't introduce any failing cases in the existing test suite). I can actually still find one edge case to do with cascading merging interlinked many to many associations that this doesn't fix, but I was planning to open that as a new ticket after this My feeling is that the current merge already has issues and this definitely improves it.

Comment by Benjamin Eberlei [ 01/Nov/10 ]

It cannot happen inside a single merge, single merges use the $visited to avoid infinite recursions, each entity can only be merged once inside a single merge operation.

Comment by Benjamin Eberlei [ 10/Nov/10 ]

Added a note into the documentation about using EntityManager#clear between merging of entities which share subgraphs and cascade merge.

Handling this issue in UnitOfwork will be declared an improvement, not a bug anymore and be scheduled for later releases. The required changes to the core are to dangerous and big.

Comment by Dave Keen [ 11/Nov/10 ]

Where in the docs is that?

Just to summarize, the equivalent operation to having multiple merges and a single flush is to call merge followed by flush each time, with the whole thing surrounded by a transaction? Does this have a big impact on performance?

Comment by Dave Keen [ 11/Nov/10 ]

Ben - even given the decision not to implement this (and I do understand your thinking, as it is a major change), is there any reason not to implement the bit that ensures that the same entity isn't added to a collection twice during a merge? I can't think of a situation where this should be allowed, and I have a use case where I get 'DUPLICATE KEY' errors if this isn't there.

Please see attached patch.

Comment by Benjamin Eberlei [ 11/Nov/10 ]

What bit of that huge patch is that? Can you extract it into another ticket if thats possible?

Comment by Benjamin Eberlei [ 11/Nov/10 ]

I added it to "Working with Objects" and the descripton of Merge. Its not yet live on the site.

Using this current workaround has a performance impact, since more SELECT statements have to be issued against the database.

Comment by Dave Keen [ 11/Nov/10 ]

Apologies for not being clear - only the 3rd patch (multipleaddmerge.diff) is relevant to the 'DUPLICATE KEY' error I am now talking about, but I'll put it in a nother ticket if you prefer.

Comment by Benjamin Eberlei [ 11/Nov/10 ]

please add a new ticket, patch looks good.

Comment by Dave Keen [ 11/Nov/10 ]

Created as DDC-875





Add the notion of read-only entities (DDC-209)

[DDC-691] doctrine.readOnly query hint Created: 15/Jul/10  Updated: 31/May/12

Status: Open
Project: Doctrine 2 - ORM
Component/s: DQL, ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Sub-task Priority: Minor
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 6
Labels: None


 Description   

Setting such a query hint to TRUE should result in all entities being retrieved by that query to be read-only for the purposes of change-tracking. Note that the entities themselves need not necessarily be read-only in general.

This feature is a flush performance tweak that can be used to query for objects but not let the returned objects run through change-tracking on flush. Any other managed objects are tracked as usual so you can do a read-only query for 100 entities and persist a new entity in the same unit of work with optimal flushing performance.



 Comments   
Comment by Konstantin [ 26/Dec/11 ]

Any news?
Why query hint? What about temporary switching like fetch mode changing via query object?

Comment by Gigi Largeanus [ 31/May/12 ]

Any news on this?

I think this is a must have feature. Thanks for all your work.





[DDC-676] Find a way to test serialize/unserialize of all ClassMetadata properties in isolation Created: 10/Jul/10  Updated: 29/Aug/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

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


 Description   

We should find a way, using PHPUnit Data Providers or anything else, to check the serialize/unserialize of every property in the ClassMetadata instance, since errors here can be very subtle but dangerous.






[DDC-668] add upsert support Created: 04/Jul/10  Updated: 20/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Lukas Kahwe Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 4
Labels: None


 Description   

Didnt find anything in the docs on this. Is D2 capable of doing an UPSERT [1] in case I am trying to persist an object that may or may not have been saved previously. Different RDBMS support different syntax for this case. Like MySQL has INSERT .. ON DUPLICATE KEY UPDATE (or even INSERT IGNORE) while the SQL standard defines a MERGE syntax which seems to be gaining support. Of course you can always fallback to a SELECT FOR UPDATE (or if you want to be hacky an INSERT which catches duplicate key violations .. but probably not a good idea since many RDBMS rollback on a failure inside a transaction).

[1] http://en.wikipedia.org/wiki/Upsert

See also http://opensource.atlassian.com/projects/hibernate/browse/HHH-3011 asking for MERGE support

Ideally there would be a way to define on a model or model instance level if merge logic should be applied.



 Comments   
Comment by Robert Burkhead [ 09/Jul/10 ]

Doctrine_Record defines a replace() method.

In the MySQL Doctrine implementation, however, it is not the same as INSERT .. ON DUPLICATE KEY UPDATE. The replace() method implemented in Doctrine_Connection_Mysql uses the REPLACE INTO syntax, which is a DELETE and then INSERT when the key exists. This is fine, except for tables that use auto-increment fields. The delete-then-insert operation yields a new auto-incremented value, whereas INSERT .. ON DUPLICTATE KEY UPDATE would not.

Comment by Lukas Kahwe [ 09/Jul/10 ]

MySQL (and SQLite) REPLACE is a no go. It causes way too much disc I/O and worse yet totally screws up the on disk data structures because of the deleting.

Comment by Benjamin Eberlei [ 31/Jul/11 ]

Scheduled for 2.2

Comment by Benjamin Eberlei [ 31/Jul/11 ]

Evaluating this makes me sad, except MySQL support for this is rather non-existant, and the oracle merge is aiming at batch operations.

Comment by Benjamin Eberlei [ 22/Oct/11 ]

Should this be done with

1. Select first, then insert
2. Catch and evaluate exception then update

I am leaning towards 1.

Comment by Guilherme Blanco [ 20/Dec/11 ]

Updating fix version





[DDC-667] Lock Timeout Query Hint for DQL Queries Created: 04/Jul/10  Updated: 16/Sep/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-BETA2
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: None


 Description   

After the implementation of DDC-178 there is now only outstanding the support for locking queries based on a given timeout.

This will be a DQL query feature only and be available via a query hint:

$query->setHint(Query::LOCK_TIMEOUT, $timeoutMs);

It will be only working on Oracle.



 Comments   
Comment by Roman S. Borschel [ 30/Aug/10 ]

If this is to be implemented for 2.0, it needs to happen for RC1, therefore rescheduling to RC1. Feel free to reschedule to 2.x if necessary.

Comment by Benjamin Eberlei [ 16/Sep/10 ]

Only oracle supports lock timeouts and no other vendor seems to plan to support it. I move to 2.x, but i guess this would rather be an issue of user extension.





Allow @Id on @ManyToOne fields (DDC-117)

[DDC-658] Reverse engineering with Oracle (DBDriver and Associations as Identifier) Created: 27/Jun/10  Updated: 11/Dec/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Sub-task Priority: Major
Reporter: Mickael Perraud Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: None
Environment:

Ubuntu 10.04 + Oracle 11g Entreprise + PHP 5.3.2 + Doctrine2 Git (up-to-date)



 Description   

I am playing with reverse engineering with Oracle and I have some problems:

My schema:

drop table PHONE_NUMBER;
drop table CUSTOMER;

create table CUSTOMER (
   CUSTOMER_ID             NUMBER(4)                       not null,
   CUSTOMER_LASTNAME       VARCHAR2(50)                    not null,
   CUSTOMER_MODIFIED       DATE,
   constraint PK_CUSTOMER primary key (CUSTOMER_ID)
         using index
       tablespace TBS_INDEX
       storage
       (
           initial 100K
           next 100K
       )
)
storage
(
    initial 100K
    next 100K
)
tablespace TBS_DATA;

create table PHONE_NUMBER (
   PHONE_NUMBER_ID         NUMBER(4)                       not null,
   CUSTOMER_ID             NUMBER(4)                       not null,
   PHONE_NUMBER            VARCHAR2(50)                    not null,
   PHONE_NUMBERMODIFIED    DATE,
   constraint PK_PHONE_NUMBER primary key (PHONE_NUMBER_ID, CUSTOMER_ID)
         using index
       tablespace TBS_INDEX
       storage
       (
           initial 100K
           next 100K
       )
)
storage
(
    initial 100K
    next 100K
)
tablespace TBS_DATA;

alter table PHONE_NUMBER
   add constraint PHONE_NUMBER__CUSTOMER foreign key (CUSTOMER_ID)
      references CUSTOMER (CUSTOMER_ID);

I obtain "Fatal error: Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Property "customerId" in "PhoneNumber" was already declared, but it must be declared only once'"

It's because a foreign key is a component of the primary key.



 Comments   
Comment by Mickael Perraud [ 28/Jun/10 ]

This is the continuation of http://www.doctrine-project.org/jira/browse/DDC-616. Only the schema is different.

Comment by Benjamin Eberlei [ 28/Jun/10 ]

just for understanding this scenario:

Is this a One-To-One relation and the TABLE_TEST2 "inherits" the primary key from its parent TABLE_TEST1?

If yes, this construct is not yet supported by Doctrine 2, we still need to include an ID-Generator that supports this kind of schema.

Comment by Mickael Perraud [ 28/Jun/10 ]

Change for a more understandable use case. Note that it's not my real use case and that I work on legacy database on which I can't change the structure.

Comment by Benjamin Eberlei [ 01/Jan/11 ]

updated the issue topic to get a better grasp of what needs to be done here.

Comment by waldo [ 09/Jun/11 ]

I have the same error with Mysql whit the same condition.

Comment by Benjamin Eberlei [ 28/Nov/11 ]

More details on the work to be done:

The relevant code is in Doctrine/ORM/Mapping/Driver/DatabaseDriver.php only.

The idea is currently many-to-many tables are detected by checking that the table has foreign keys on all the primary key columns (no additional columns!)

Now with the 2.1 feature of foreign key/primary key entities this is not necessarily true anymore. You can have the primary keys being foreign keys BUT have additional columns that are not part of the primary key. This has to be detected.

If a foreign key-primary-key entity is found that has additional columns a ClassMetadata has to be created and the associations have to be created with the "id" => true flag in mapManyToOne().

Comment by Scott Steffens [ 11/Dec/11 ]

For what it's worth, I'm getting this error when I have a PK that is a single column and not a FK.

PRIMARY KEY (`id`),
UNIQUE KEY `cycle_station_id` (`cycle`,`station_id`),
KEY `station_id_idx` (`station_id`),
KEY `readings` (`readings`),
KEY `source` (`source`),
KEY `temperature_min_max` (`temperature_max`,`temperature_min`),
KEY `station_id_cycle` (`station_id`,`cycle`,`updated_at`),
CONSTRAINT `compiled_1_station_id_stations_id` FOREIGN KEY (`station_id`) REFERENCES `stations` (`id`),
CONSTRAINT `compiled_1_station_id_stations_id_1` FOREIGN KEY (`station_id`) REFERENCES `stations` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=160833690 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci





[DDC-624] Partial object query that leaves out an association to avoid loading it fetches the association anyway. Created: 03/Jun/10  Updated: 11/Nov/11

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-BETA1
Fix Version/s: 2.x
Security Level: All

Type: Bug Priority: Major
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 2
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-1465 Fetching partial objects doesn't work... Open

 Description   

Assuming:

Customer <onetoone> Cart

where Cart is the owning side.

Since the association from Customer to Cart can not be lazy, it would make sense to leave out the association in a query to avoid loading the carts like this:

select partial c.{id,name, ... anything except cart} from Customer c"

But this is ignored and the carts of all customers are fetched anyway. Query::HINT_FORCE_PARTIAL_LOAD is an alternative solution, however it has the disadvantage that it disables lazy-loading for all queried objects. If partial querying would honor associations this would allow more fine-grained control.



 Comments   
Comment by Roman S. Borschel [ 26/Aug/10 ]

Might need to be pushed back to a 2.0.x / 2.x.x bugfix release. Not clear yet.





[DDC-585] Create a coding standards document Created: 13/May/10  Updated: 17/Apr/14

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Documentation Priority: Major
Reporter: Roman S. Borschel Assignee: Jonathan H. Wage
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We need a new coding standards document for Doctrine 2.



 Comments   
Comment by Benjamin Morel [ 29/Jan/13 ]

Has there been any work on a coding standards document yet?
I'm currently working on fixing documentation on this project, and it might be a good time to define a standard.
I've started compiling a few recommendations based on various feedbacks I've got in my pull requests, and I can post them here.
Please let me know if there have been previous attempts so far!

Comment by Marco Pivetta [ 29/Jan/13 ]

Benjamin Morel Guilherme Blanco may have a CS ruleset, but it's not ready yet. Perfect timing btw, we really need to automate this to avoid having all these useless CS fix comments in pull requests

Comment by Benjamin Morel [ 29/Jan/13 ]

Ok, I'll post my document here once ready, and Guilherme Blanco will be able to compare it with his ruleset!

Comment by Benjamin Morel [ 30/Jan/13 ]

Here is a first draft: https://gist.github.com/4676670

Please comment!

Comment by Benjamin Morel [ 11/Feb/13 ]

Guilherme Blanco, if you don't have time to compare your ruleset with my draft, maybe you could publish your current ruleset so that others can have a look?

Comment by Benjamin Morel [ 02/Aug/13 ]

Any update guys? I'm willing to spend some time on this work, but if no one answers, we won't be going forward

Comment by Marco Pivetta [ 02/Aug/13 ]

Benjamin Morel I think a pull request against the doctrine website (https://github.com/doctrine/doctrine-website-sphinx) would be fine...

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

This should go into https://github.com/doctrine/coding-standard repo (long term).





[DDC-445] Evaluate possible ways in which stored procedures can be used Created: 19/Mar/10  Updated: 24/Dec/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Minor
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Reference
relates to DDC-391 Allow to specifiy custom Entity and C... In Progress

 Description   

We should evaluate the current situation of stored procedure support as well as where we want to go with it / how far we want to support it, if at all.



 Comments   
Comment by Benjamin Eberlei [ 19/Mar/10 ]

I think this relates to the usage of Custom Persisters





[DDC-391] Allow to specifiy custom Entity and Collection Persister classes Created: 06/Mar/10  Updated: 08/Sep/13

Status: In Progress
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-ALPHA4
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Minor
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 8
Labels: None

Issue Links:
Reference
is referenced by DDC-2637 [GH-769] Add Custom Persisters Open
is referenced by DDC-445 Evaluate possible ways in which store... Open
is referenced by DDC-699 ProxyFactory: allow to overwrite $_pr... Resolved

 Description   

It should be allowed to overwrite the default persisters for collections and entities. This should go along the lines of Hibernate which allows to set the custom implementations like:

XML:

<entity persister="persisterClass" />
<OneToMany persister="persisterClass" />

Annotation

/**
 * @Entity(persister="persisterClass")
 * @OneToMany(persister="persisterClass")
 */


 Comments   
Comment by Roman S. Borschel [ 19/May/10 ]

Rescheduling for beta3.

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 any larger new features for 2.0.

Comment by Benjamin Eberlei [ 13/Oct/10 ]

implemented this in a feature branch for now, it really doesnt touch any other runtime code so maybe we can still merge this before RC1

http://github.com/doctrine/doctrine2/tree/OverridePersisters

Comment by Gediminas Morkevicius [ 25/Feb/11 ]

Is this forgotten? you should merge it since it does not affect any other parts of ORM, this is a great feature

Comment by Benjamin Eberlei [ 26/Feb/11 ]

This has not been forgotten, but the Persister is due for a heavy refactoring for 2.2 probably, when we will make it use the SQL Query object that we are working on.

So I cannot merge this, because the API will probably break big time.

Comment by Jonas Wouters [ 16/Mar/11 ]

Does that mean we will not see this feature before 2.2?

Comment by Benjamin Eberlei [ 16/Mar/11 ]

Yes, that is correct. I dont want to add it as experimental/undocumented feature because people will take it for granted and make us responsible for possible bc breaks.

I will update the target version accordingly.

Sorry for disappointing you, but this feature is fundamentally important at the core of the library. That means we have to get it right and not rush into it.

Comment by Gediminas Morkevicius [ 17/Mar/11 ]

Just as I thought that first you will want to make a query builder object for all persisters. since now they use plain sql. Thanks for all your work on this

Comment by Adam Brodziak [ 11/Jan/12 ]

I might be mistaken, but AFAICS mentioned Persister heavy refactoring did not made through to 2.2 version. Is there any plan to have it in 2.3 or at any later stage?

Comment by Guilherme Blanco [ 13/Jan/12 ]

@Adam I refactored all Persisters optimizing their code, but I could not complete the move from SQL string generation to Doctrine\DBAL\Query.
We missed it, yes. I may reschedule for 2.3

Comment by Thomas Rothe [ 05/Sep/12 ]

Why is it still missing in 2.3? I would require this for an extension that uses its own overridden entity persister and using a custom persister is the solution that you guys recomend for not overriding the entity manager.

Comment by sebastiaan stok [ 23/Sep/12 ]

Any change seeing this soon? I really need this for a security feature.

What is making this so hard? just adding an setEntityPersister($entityName, $object) should do the trick.
I don't need any fancy stuff, just a way to limit the fields in the SELECT list.

Edit: OK, I'm shot I CAN NOT overwrite the entity manager as the UnitOfWork is private!
Got any other idea?

Comment by Stefan Kögel [ 24/Sep/12 ]

Any chance you could add this quickly? I need this feature urgently to complete an extension using a custom persister. Thanks in advance.

Comment by Lennart Weijl [ 09/Jul/13 ]

What's the status on this issue?





[DDC-298] Allow Entity to hold a collection of a single primitive type Created: 02/Feb/10  Updated: 20/Dec/13

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

Type: New Feature Priority: Major
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 5
Labels: None

Issue Links:
Duplicate
is duplicated by DDC-2806 @ElementCollection does work as expected Resolved

 Description   

Sometimes you want to save arbitrary information for an entity using a key -> value array-structure. JPA supports this by means of the @ElementCollection annotation with allows to specify HashMaps for example.

I propose a new AssocationMapping called "ElementMapping" / "ElementCollection" and annotations (options):

ElementCollection
+ elementTable
+ keyType
+ keyLength
+ keyColumnDefinition
+ valueType
+ valueLength
+ valueColumnDefinition

The key and value definitions are necessary for converting and schema generation.

The implementation would make use of the PersistentCollection at all times and work as any other persistent collection just with primitive types.

Restrictions for a first implementation:

  • Only available as a Lazy-Load Collection, no hydration with the source entity
  • Can't be used in queries alike "entity.colname.key = ?1"

Use-Case:

$entity->options['foo'] = 'bar';
$entity->options['bar'] = 'baz';

This could be done for 2.0 imho, adding the necessary changes and optimizations could then be scheduled for 2.1



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

In this implementation Schema-Tool would generate a table:

elementTable (entity_id-1, ..., entity_id-n, key, value) and using the Platform Type Generation of keyType and valueType

Comment by Benjamin Eberlei [ 02/Feb/10 ]

Column Names should be Change-able also since there could be people who name their primary keys "key" and "value" o_O

Comment by Benjamin Eberlei [ 02/Feb/10 ]

Ordering could be implemented on top of this using the @OrderColumn JPA implementation by adding another column to the table with a numeric order that will be "order by"'d on select time.

Comment by Benjamin Eberlei [ 24/Dec/10 ]

Pushed back

Comment by Richard Michael Coo [ 10/Oct/13 ]

Any news on this? It has been almost 3 years since its last update =)





[DDC-128] Consider adding EntityManager#link/unlink methods for direct association manipulation Created: 07/Nov/09  Updated: 29/Dec/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-ALPHA2
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Major
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Reference
is referenced by DDC-546 New fetch mode EXTRA_LAZY for collect... Resolved

 Description   

A problem when working with collection-valued associations is that almost all operations except add($obj) require the collection to become initialized in order for the operation to be performed properly. While this is all correct and beautiful OO-wise it may be problematic at times with regards to performance. Hence we might want to consider to provide some convenient methods along the lines of link/unlink (name suggestions?) which allow more direct, less OO collection manipulation. Such methods obviously would bypass the normal object lifecycle and the changes done through these methods will not be reflected in the in-memory objects and collections, unless the user keeps them in-synch himself.



 Comments   
Comment by Benjamin Eberlei [ 11/Dec/09 ]

Questions

  • I suppose link and unlinked entities would then handled by UnitOfwork commit also?
  • Since the collection is not initialized, one does not know upfront if the action will be successful, what happens if:
    • an entity is linked with a collection, although they are already connected.
    • an entity is unlinked from a collection it is not in.

Regarding the naming, i like link/unlink.

Comment by Roman S. Borschel [ 17/Dec/09 ]

What do you mean by "handled by UnitOfWork commit" ? Whether the SQL is "scheduled" or executed immediately? Interesting question.
Scheduling would probably be better but also more difficult.

As far as usage is concerned, I currently imagine it as follows:

// EntityManager#link($sourceObj, $field, $targetObj)
$user = $em->getReference($userId); // $userId probably from request parameters
$address = $em->getReference($addressId); // $addressId probably from request parameters
$em->link($user, 'addresses', $address);

"What happens if: an entity is linked with a collection, although they are already connected."

Probably an SQL error which results in an exception from the driver. Depends on the database constraints though.

"What happens if: an entity is unlinked from a collection it is not in"

Probably nothing, at least not from the SQL side. An exception could be thrown from Doctrine itself if the update affected 0 rows.

Thanks for these initial questions. Thats definitely food for thought. Keep it coming.

Comment by Roman S. Borschel [ 26/Aug/10 ]

Pushed back.





[DDC-54] Trigger postLoad events and callbacks after associations have been initialized Created: 15/Oct/09  Updated: 03/Sep/13

Status: In Progress
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.0-ALPHA2
Fix Version/s: 2.x
Security Level: All

Type: Improvement Priority: Major
Reporter: Roman S. Borschel Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 7
Labels: None


 Description   

Currently the postLoad events and callbacks are triggered after the entity has been created and filled with its "primitive" state but before associations are available. The postLoad events and callbacks should be postponed so that they are triggered after associations have been initialized.



 Comments   
Comment by Roman S. Borschel [ 30/Aug/10 ]

If this is to be included in 2.0 it needs to happen for RC1. However, it is not clear yet whether it will be done in time.

Comment by Benjamin Eberlei [ 23/Sep/10 ]

How would you solve this Roman? I thought of adding a query hint so that the postLoad inside unit of work is not triggered and gathering all the entities that have a post load event in an array inside the object hydrator, then iterating it after taking the snapshots of all collections inside hydrateAll

Comment by Roman S. Borschel [ 24/Sep/10 ]

@Benjamin: Not sure what you would use the query hint for but in general that is the approach I had in mind, yes. You can't get around iterating over the entities after the actual hydration.

Comment by Benjamin Eberlei [ 27/Sep/10 ]

The query hint would do something like:

        //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
        if (isset($class->lifecycleCallbacks[Events::postLoad]) && !isset($hints['hydrationPostLoad'])) {
            $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
        }
        if ($this->evm->hasListeners(Events::postLoad) && !isset($hints['hydrationPostLoad'])) {
            $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
        }

another way would be to move that code out of UoW::createEntity completly and have the persisters call it when they use that method.

Comment by Roman S. Borschel [ 28/Sep/10 ]

Leaving that code in UoW does not make sense to me, if it is moved, it needs to be moved completely. Why do you think the persisters should do it? Initially I thought collecting the affected entities during hydration and then when hydration is done iterating over them and triggering the postLoad events.

Comment by Benjamin Eberlei [ 28/Sep/10 ]

Yes but postLoad has to be triggered for non Hydrated entities (i.e. Persister) also

Comment by Benjamin Eberlei [ 30/Oct/10 ]

Moved back

Comment by Kacper Gunia [ 15/Apr/12 ]

Hi Gyus, I need access to associations in postLoad or similar event, and my idea is to dispatch new event after full initialisation of object, what do You think about it? If I can help please let me know It's important for me.

Comment by Alexander Pasichnick [ 25/Sep/12 ]

Now in my PostLoad access to associations is work fine. Why this issue is still in Unresolved status?

Comment by Łukasz Cybula [ 11/Oct/12 ]

What do you (Roman and Benjamin) think about adding postHydrate event which would be called within ObjectHydrator::hydrateAllData() on every entity collected during hydration? I could prepare a patch for this. I personally think this would be better than adding a hint that changes behaviour of postLoad event.

Comment by Slavik Derevyanko [ 07/Jun/13 ]

Just stumbled upon this issue. Seems like my associated entities aren't yet loaded in PostLoad event handler.
Doctrine version "doctrine/orm": "2.3.1"

I've noticed that I have two different paths of execution:
1. When the find() method is used to retrieve the entity, SimpleObjectHydrator is used to perform a hydration and the associations are made available in PostLoad event:
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateRowData : lineno 135() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 135
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php.Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator->hydrateAllData : lineno 50() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php at line 50
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php.Doctrine\ORM\Persisters\BasicEntityPersister->load : lineno 678() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php at line 678
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php.Doctrine\ORM\EntityManager->find : lineno 413() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 413
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php.Doctrine\ORM\EntityRepository->find : lineno 131() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php at line 131

2. When the DQL is used, ObjectHydrator is used to perform a hydration, and the associations aren't made ready in PostLoad event:
bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php.BVD\PetroleumBundle\Entity\FuelCard->retrieveNumbers : lineno 304() bvdpetroleum/src/BVD/PetroleumBundle/Entity/FuelCard.php at line 304
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php.Doctrine\ORM\Mapping\ClassMetadataInfo->invokeLifecycleCallbacks : lineno 2312() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php at line 2312
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php.Doctrine\ORM\UnitOfWork->createEntity : lineno 2610() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 2610
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->_getEntity : lineno 245() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 245
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateRowData : lineno 478() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 478
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php.Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateAllData : lineno 149() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 149
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php.Doctrine\ORM\Internal\Hydration\AbstractHydrator->hydrateAll : lineno 111() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php at line 111
bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php.Doctrine\ORM\AbstractQuery->execute : lineno 747() bvdpetroleum/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php at line 747

Hope this helps to solve the issue.

Comment by Valera Leontyev [ 03/Sep/13 ]

This issue is very important in my opinion. I can't come up with any workaround to resolve it. Only possible way to detect fully loaded state is to call entity method from outside which is too rude and dirty.





[DDC-17] Ability to skip the operation from a pre-operation event handler Created: 20/Sep/09  Updated: 26/Aug/10

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: 2.x
Security Level: All

Type: New Feature Priority: Minor
Reporter: Ismo Toijala Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In Doctrine 1.1 it is possible to skip the operation in the event handlers in Doctrine_Record_Listener using Doctrine_Event::skipOperation.

This no longer seems to be possible in Doctrine 2.0 Alpha 1, for example when handling a preRemove event to implement soft-delete behaviour. Perhaps a method could be added to \Doctrine\Common\EventArgs\LifecycleEventArgs to skip the operation, at least before the operation.

Without this implementing soft-delete would require the user to update deleted_at and deleted_by himself and then save the record. It could no longer be done automatically when removing a record because the record is then removed.



 Comments   
Comment by Roman S. Borschel [ 20/Sep/09 ]

The problem is, full support for soft-delete throughout the system is not feasible and very fragile. Simple soft-delete through skipping the delete operation is the easiest part. Then you will probably want to modify all DQL queries so that they adhere to it automatically and then there will always be still queries that do NOT go through DQL, like even internal lazy-load queries or native queries or others, which would need to be modified also.

To sum it up, implementing soft-delete "inside" doctrine is absolutely not worth the effort and imho a bad idea and I'm certainly not willing to make lots of adjustments to the core that have a negative impact on performance just to make this soft-delete possible.

I really recommend handling "soft" deletes yourself, the normal way, by simply abstracting entity retrieval and persistence through a DAO/repository layer. As a nice side-effect you get less magic and it still works when you swap out doctrine for another persistence provider.

I am willing to add support for skipping deletes and maybe some other operations through events but I'm not willing to go any further, as explained above.





[DDC-4] Implement support for Concrete Table Inheritance Created: 09/Sep/09  Updated: 24/Dec/10

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

Type: Improvement Priority: Minor
Reporter: Roman S. Borschel Assignee: Roman S. Borschel
Resolution: Unresolved Votes: 0
Labels: None


 Description   

A first implementation could probably live without support for polymorphic queries (requires SQL UNIONs to be generated).






Generated at Tue Sep 23 10:28:51 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.