[2.0] Class table inheritance updates. Started work on self-referencing associations.
This commit is contained in:
parent
c9cc9f1373
commit
b66d530540
14 changed files with 200 additions and 121 deletions
|
@ -409,7 +409,7 @@ class Connection
|
|||
*/
|
||||
public function fetchAll($sql, array $params = array())
|
||||
{
|
||||
return $this->execute($sql, $params)->fetchAll(PDO::FETCH_ASSOC);
|
||||
return $this->execute($sql, $params)->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
namespace Doctrine\ORM;
|
||||
|
||||
/**
|
||||
* A repository provides the illusion of an in-memory Entity store.
|
||||
* Base class for all custom user-defined repositories.
|
||||
* Provides basic finder methods, common to all repositories.
|
||||
* An EntityRepository serves as a repository for entities with generic as well as
|
||||
* business specific methods for retrieving entities.
|
||||
*
|
||||
* This class is designed for inheritance and users can subclass this class to
|
||||
* write their own repositories.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
|
|
|
@ -95,9 +95,12 @@ class ObjectHydrator extends AbstractHydrator
|
|||
$this->_fetchedAssociations[$assoc->sourceEntityName][$assoc->sourceFieldName] = true;
|
||||
if ($assoc->mappedByFieldName) {
|
||||
$this->_fetchedAssociations[$assoc->targetEntityName][$assoc->mappedByFieldName] = true;
|
||||
} else if ($inverseAssoc = $this->_em->getClassMetadata($assoc->targetEntityName)
|
||||
->inverseMappings[$assoc->sourceFieldName]) {
|
||||
$this->_fetchedAssociations[$assoc->targetEntityName][$inverseAssoc->sourceFieldName] = true;
|
||||
} else {
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
if (isset($targetClass->inverseMappings[$assoc->sourceFieldName])) {
|
||||
$inverseAssoc = $targetClass->inverseMappings[$assoc->sourceFieldName];
|
||||
$this->_fetchedAssociations[$assoc->targetEntityName][$inverseAssoc->sourceFieldName] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,10 +233,11 @@ class ObjectHydrator extends AbstractHydrator
|
|||
}
|
||||
}
|
||||
|
||||
private function getEntity(array $data, $className)
|
||||
private function getEntity(array $data, $dqlAlias)
|
||||
{
|
||||
if (isset($this->_rsm->discriminatorColumns[$className])) {
|
||||
$discrColumn = $this->_rsm->discriminatorColumns[$className];
|
||||
$className = $this->_rsm->aliasMap[$dqlAlias];
|
||||
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
|
||||
$discrColumn = $this->_rsm->discriminatorColumns[$dqlAlias];
|
||||
$className = $this->_discriminatorMap[$className][$data[$discrColumn]];
|
||||
unset($data[$discrColumn]);
|
||||
}
|
||||
|
@ -351,7 +355,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
$indexIsValid = $index !== false ? $this->isIndexKeyInUse($baseElement, $relationAlias, $index) : false;
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
$element = $this->getEntity($data, $entityName);
|
||||
$element = $this->getEntity($data, $dqlAlias);
|
||||
|
||||
// If it's a bi-directional many-to-many, also initialize the reverse collection.
|
||||
if ($relation->isManyToMany()) {
|
||||
|
@ -393,7 +397,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
if ( ! isset($nonemptyComponents[$dqlAlias])) {
|
||||
//$this->setRelatedElement($baseElement, $relationAlias, null);
|
||||
} else {
|
||||
$this->setRelatedElement($baseElement, $relationAlias, $this->getEntity($data, $entityName));
|
||||
$this->setRelatedElement($baseElement, $relationAlias, $this->getEntity($data, $dqlAlias));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +415,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
$this->_rootAliases[$dqlAlias] = true; // Mark as root alias
|
||||
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->getEntity($rowData[$dqlAlias], $entityName);
|
||||
$element = $this->getEntity($rowData[$dqlAlias], $dqlAlias);
|
||||
if ($field = $this->_getCustomIndexField($dqlAlias)) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array(
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Doctrine\ORM;
|
|||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class NativeQuery extends AbstractQuery
|
||||
final class NativeQuery extends AbstractQuery
|
||||
{
|
||||
private $_sql;
|
||||
|
||||
|
|
|
@ -199,78 +199,64 @@ class JoinedSubclassPersister extends StandardEntityPersister
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds all parent classes as INNER JOINs and subclasses as OUTER JOINs
|
||||
* to the query.
|
||||
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||
*
|
||||
* Callback that is invoked during the SQL construction process.
|
||||
*
|
||||
* @return array The custom joins in the format <className> => <joinType>
|
||||
* @param array $criteria
|
||||
* @return string The SQL.
|
||||
* @todo Quote identifier.
|
||||
* @override
|
||||
*/
|
||||
/*public function getCustomJoins()
|
||||
protected function _getSelectSingleEntitySql(array $criteria)
|
||||
{
|
||||
$customJoins = array();
|
||||
$classMetadata = $this->_classMetadata;
|
||||
foreach ($classMetadata->parentClasses as $parentClass) {
|
||||
$customJoins[$parentClass] = 'INNER';
|
||||
$tableAliases = array();
|
||||
$aliasIndex = 1;
|
||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||
$baseTableAlias = 't0';
|
||||
|
||||
foreach (array_merge($this->_class->subClasses, $this->_class->parentClasses) as $className) {
|
||||
$tableAliases[$className] = 't' . $aliasIndex++;
|
||||
}
|
||||
|
||||
$columnList = '';
|
||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||
$tableAlias = isset($mapping['inherited']) ?
|
||||
$tableAliases[$mapping['inherited']] : $baseTableAlias;
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $tableAlias . '.' . $this->_class->columnNames[$fieldName];
|
||||
}
|
||||
foreach ($classMetadata->subClasses as $subClass) {
|
||||
if ($subClass != $this->getComponentName()) {
|
||||
$customJoins[$subClass] = 'LEFT';
|
||||
|
||||
$sql = 'SELECT ' . $columnList . ' FROM ' . $this->_class->primaryTable['name']. ' ' . $baseTableAlias;
|
||||
|
||||
// INNER JOIN parent tables
|
||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$tableAlias = $tableAliases[$parentClassName];
|
||||
$sql .= ' INNER JOIN ' . $parentClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
return $customJoins;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Adds the discriminator column to the selected fields in a query as well as
|
||||
* all fields of subclasses. In Class Table Inheritance the default behavior is that
|
||||
* all subclasses are joined in through OUTER JOINs when querying a base class.
|
||||
*
|
||||
* Callback that is invoked during the SQL construction process.
|
||||
*
|
||||
* @return array An array with the field names that will get added to the query.
|
||||
*/
|
||||
/*public function getCustomFields()
|
||||
{
|
||||
$classMetadata = $this->_classMetadata;
|
||||
$conn = $this->_conn;
|
||||
$discrColumn = $classMetadata->discriminatorColumn;
|
||||
$fields = array($discrColumn['name']);
|
||||
if ($classMetadata->subClasses) {
|
||||
foreach ($classMetadata->subClasses as $subClass) {
|
||||
$fields = array_merge($conn->getClassMetadata($subClass)->fieldNames, $fields);
|
||||
}
|
||||
}
|
||||
return array_unique($fields);
|
||||
}*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @todo Looks like this better belongs into the ClassMetadata class.
|
||||
*/
|
||||
/*public function getOwningClass($fieldName)
|
||||
{
|
||||
$conn = $this->_conn;
|
||||
$classMetadata = $this->_classMetadata;
|
||||
if ($classMetadata->hasField($fieldName) && ! $classMetadata->isInheritedField($fieldName)) {
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
foreach ($classMetadata->parentClasses as $parentClass) {
|
||||
$parentTable = $conn->getClassMetadata($parentClass);
|
||||
if ($parentTable->hasField($fieldName) && ! $parentTable->isInheritedField($fieldName)) {
|
||||
return $parentTable;
|
||||
// OUTER JOIN sub tables
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $tableAliases[$subClassName];
|
||||
$sql .= ' LEFT JOIN ' . $subClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ((array)$classMetadata->subClasses as $subClass) {
|
||||
$subTable = $conn->getClassMetadata($subClass);
|
||||
if ($subTable->hasField($fieldName) && ! $subTable->isInheritedField($fieldName)) {
|
||||
return $subTable;
|
||||
}
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$conditionSql .= $baseTableAlias . '.' . $this->_class->columnNames[$field] . ' = ?';
|
||||
}
|
||||
|
||||
throw \Doctrine\Common\DoctrineException::updateMe("Unable to find defining class of field '$fieldName'.");
|
||||
}*/
|
||||
return $sql . ' WHERE ' . $conditionSql;
|
||||
}
|
||||
}
|
|
@ -199,26 +199,21 @@ class StandardEntityPersister
|
|||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that is invoked during the SQL construction process.
|
||||
*/
|
||||
public function getCustomJoins()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that is invoked during the SQL construction process.
|
||||
*/
|
||||
public function getCustomFields()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the data changeset of an entity for database insertion.
|
||||
* The array that is passed as the second parameter is filled with
|
||||
* <columnName> => <value> pairs during this preparation.
|
||||
* <columnName> => <value> pairs, grouped by table name, during this preparation.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* array(
|
||||
* 'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...),
|
||||
* 'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...),
|
||||
* ...
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* Notes to inheritors: Be sure to call <code>parent::_prepareData($entity, $result, $isInsert);</code>
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $result The reference to the data array.
|
||||
|
@ -227,7 +222,9 @@ class StandardEntityPersister
|
|||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
$platform = $this->_conn->getDatabasePlatform();
|
||||
foreach ($this->_em->getUnitOfWork()->getEntityChangeSet($entity) as $field => $change) {
|
||||
$uow = $this->_em->getUnitOfWork();
|
||||
|
||||
foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
|
||||
$oldVal = $change[0];
|
||||
$newVal = $change[1];
|
||||
|
||||
|
@ -239,6 +236,18 @@ class StandardEntityPersister
|
|||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: If the one-one is self-referencing, check whether the referenced entity ($newVal)
|
||||
// is still scheduled for insertion. If so:
|
||||
// 1) set $newVal = null, so that we insert a null value
|
||||
// 2) schedule $entity for an update, so that the FK gets set through an update
|
||||
// later, after the referenced entity has been inserted.
|
||||
//$needsPostponedUpdate = ...
|
||||
/*if ($assocMapping->sourceEntityName == $assocMapping->targetEntityName &&
|
||||
isset($this->_queuedInserts[spl_object_hash($entity)])) {
|
||||
echo "SELF-REFERENCING!";
|
||||
}*/
|
||||
|
||||
foreach ($assocMapping->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
$otherClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
if ($newVal === null) {
|
||||
|
@ -283,7 +292,7 @@ class StandardEntityPersister
|
|||
$stmt->execute(array_values($criteria));
|
||||
$data = array();
|
||||
foreach ($stmt->fetch(\PDO::FETCH_ASSOC) as $column => $value) {
|
||||
$fieldName = $this->_class->lcColumnToFieldNames[$column];
|
||||
$fieldName = $this->_class->fieldNames[$column];
|
||||
$data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName))
|
||||
->convertToPHPValue($value);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ use Doctrine\ORM\Query\QueryException;
|
|||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Query extends AbstractQuery
|
||||
final class Query extends AbstractQuery
|
||||
{
|
||||
/**
|
||||
* A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts.
|
||||
|
@ -53,32 +53,32 @@ class Query extends AbstractQuery
|
|||
/**
|
||||
* @var integer $_state The current state of this query.
|
||||
*/
|
||||
protected $_state = self::STATE_CLEAN;
|
||||
private $_state = self::STATE_CLEAN;
|
||||
|
||||
/**
|
||||
* @var string $_dql Cached DQL query.
|
||||
*/
|
||||
protected $_dql = null;
|
||||
private $_dql = null;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\Query\ParserResult The parser result that holds DQL => SQL information.
|
||||
*/
|
||||
protected $_parserResult;
|
||||
private $_parserResult;
|
||||
|
||||
/**
|
||||
* @var CacheDriver The cache driver used for caching queries.
|
||||
*/
|
||||
protected $_queryCache;
|
||||
private $_queryCache;
|
||||
|
||||
/**
|
||||
* @var boolean Boolean value that indicates whether or not expire the query cache.
|
||||
*/
|
||||
protected $_expireQueryCache = false;
|
||||
private $_expireQueryCache = false;
|
||||
|
||||
/**
|
||||
* @var int Query Cache lifetime.
|
||||
*/
|
||||
protected $_queryCacheTTL;
|
||||
private $_queryCacheTTL;
|
||||
|
||||
// End of Caching Stuff
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* Description of JoinCollectionValuedPathExpression
|
||||
* JoinAssociationPathExpression ::= JoinCollectionValuedPathExpression | JoinSingleValuedAssociationPathExpression
|
||||
* JoinCollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField
|
||||
* JoinSingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField
|
||||
*
|
||||
* @author robo
|
||||
* @todo Rename: JoinAssociationPathExpression
|
||||
|
|
|
@ -1,7 +1,22 @@
|
|||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
@ -13,6 +28,12 @@ namespace Doctrine\ORM\Query\AST;
|
|||
*/
|
||||
class StateFieldPathExpression extends Node
|
||||
{
|
||||
//const TYPE_COLLECTION_VALUED_ASSOCIATION = 1;
|
||||
//const TYPE_SINGLE_VALUED_ASSOCIATION = 2;
|
||||
//const TYPE_STATE_FIELD = 3;
|
||||
//private $_type;
|
||||
|
||||
|
||||
private $_parts;
|
||||
// Information that is attached during semantical analysis.
|
||||
private $_isSimpleStateFieldPathExpression = false;
|
||||
|
|
|
@ -71,9 +71,9 @@ class ResultSetMapping
|
|||
* @param <type> $alias
|
||||
* @param <type> $discrColumn
|
||||
*/
|
||||
public function setDiscriminatorColumn($className, $alias, $discrColumn)
|
||||
public function setDiscriminatorColumn($alias, $discrColumn)
|
||||
{
|
||||
$this->discriminatorColumns[$className] = $discrColumn;
|
||||
$this->discriminatorColumns[$alias] = $discrColumn;
|
||||
$this->columnOwnerMap[$discrColumn] = $alias;
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ class SqlWalker
|
|||
. implode(', ', array_map(array($this, 'walkSelectExpression'),
|
||||
$selectClause->getSelectExpressions()));
|
||||
|
||||
foreach ($this->_selectedClasses as $dqlAlias => $class) {
|
||||
foreach ($this->_selectedClasses as $dqlAlias => $class) {
|
||||
if ($this->_queryComponents[$dqlAlias]['relation'] === null) {
|
||||
$this->_resultSetMapping->addEntityResult($class->name, $dqlAlias);
|
||||
} else {
|
||||
|
@ -122,6 +122,7 @@ class SqlWalker
|
|||
$this->_queryComponents[$dqlAlias]['relation']
|
||||
);
|
||||
}
|
||||
|
||||
//if ($this->_query->getHydrationMode() == \Doctrine\ORM\Query::HYDRATE_OBJECT) {
|
||||
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
||||
$rootClass = $this->_em->getClassMetadata($class->rootEntityName);
|
||||
|
@ -129,7 +130,7 @@ class SqlWalker
|
|||
$discrColumn = $rootClass->discriminatorColumn;
|
||||
$columnAlias = $this->getSqlColumnAlias($discrColumn['name']);
|
||||
$sql .= ", $tblAlias." . $discrColumn['name'] . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->setDiscriminatorColumn($class->name, $dqlAlias, $columnAlias);
|
||||
$this->_resultSetMapping->setDiscriminatorColumn($dqlAlias, $columnAlias);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
@ -253,7 +254,7 @@ class SqlWalker
|
|||
$assoc = $targetQComp['relation'];
|
||||
}
|
||||
|
||||
if ($assoc->isOneToOne()/* || $assoc->isOneToMany()*/) {
|
||||
if ($assoc->isOneToOne()) {
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
||||
$joinColumns = $assoc->getSourceToTargetKeyColumns();
|
||||
$first = true;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\Models\Company;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use Doctrine\Tests\Models\Company\CompanyEmployee;
|
|||
use Doctrine\Tests\Models\Company\CompanyManager;
|
||||
|
||||
/**
|
||||
* Functional tests for the Single Table Inheritance mapping strategy.
|
||||
* Functional tests for the Class Table Inheritance mapping strategy.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
|
@ -22,7 +22,6 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
|
||||
public function testCRUD()
|
||||
{
|
||||
|
||||
$person = new CompanyPerson;
|
||||
$person->setName('Roman S. Borschel');
|
||||
|
||||
|
@ -89,4 +88,66 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
$this->assertEquals(2, $affected);
|
||||
*/
|
||||
}
|
||||
|
||||
public function testMultiLevelUpdateAndFind() {
|
||||
$manager = new CompanyManager;
|
||||
$manager->setName('Roman S. Borschel');
|
||||
$manager->setSalary(100000);
|
||||
$manager->setDepartment('IT');
|
||||
$manager->setTitle('CTO');
|
||||
$this->_em->save($manager);
|
||||
$this->_em->flush();
|
||||
|
||||
$manager->setName('Roman B.');
|
||||
$manager->setSalary(119000);
|
||||
$manager->setTitle('CEO');
|
||||
$this->_em->save($manager);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$manager = $this->_em->find('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
|
||||
|
||||
$this->assertEquals('Roman B.', $manager->getName());
|
||||
$this->assertEquals(119000, $manager->getSalary());
|
||||
$this->assertEquals('CEO', $manager->getTitle());
|
||||
$this->assertTrue(is_numeric($manager->getId()));
|
||||
}
|
||||
|
||||
public function testSelfReferencingOneToOne() {
|
||||
$manager = new CompanyManager;
|
||||
$manager->setName('John Smith');
|
||||
$manager->setSalary(100000);
|
||||
$manager->setDepartment('IT');
|
||||
$manager->setTitle('CTO');
|
||||
|
||||
$wife = new CompanyPerson;
|
||||
$wife->setName('Mary Smith');
|
||||
$wife->setSpouse($manager);
|
||||
|
||||
$this->assertSame($manager, $wife->getSpouse());
|
||||
$this->assertSame($wife, $manager->getSpouse());
|
||||
|
||||
$this->_em->save($manager);
|
||||
$this->_em->save($wife);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
//var_dump($this->_em->getConnection()->fetchAll('select * from company_persons'));
|
||||
//var_dump($this->_em->getConnection()->fetchAll('select * from company_employees'));
|
||||
//var_dump($this->_em->getConnection()->fetchAll('select * from company_managers'));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery('select p, s from Doctrine\Tests\Models\Company\CompanyPerson p join p.spouse s where p.name=\'Mary Smith\'');
|
||||
|
||||
$result = $query->getResultList();
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertTrue($result[0] instanceof CompanyPerson);
|
||||
$this->assertEquals('Mary Smith', $result[0]->getName());
|
||||
$this->assertTrue($result[0]->getSpouse() instanceof CompanyEmployee);
|
||||
|
||||
//var_dump($result);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
$users = $query->getResultList();
|
||||
|
||||
$this->assertEquals(1, count($users));
|
||||
$this->assertTrue($users[0] instanceof CmsUser);
|
||||
$this->assertEquals('Roman', $users[0]->name);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue