Commit 0f8e9e0b authored by romanb's avatar romanb

refactorings. made basic one-one, one-many joins work.

parent efca7941
......@@ -159,6 +159,7 @@ class Doctrine_Association implements Serializable
$this->_customAccessor = isset($mapping['accessor']) ? $mapping['accessor'] : null;
$this->_customMutator = isset($mapping['mutator']) ? $mapping['mutator'] : null;
$this->_isOptional = isset($mapping['isOptional']) ? (bool)$mapping['isOptional'] : true;
$this->_cascades = isset($mapping['cascade']) ? (array)$mapping['cascade'] : array();
return $mapping;
}
......
<?php
/*
* $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.phpdoctrine.org>.
*/
#namespace Doctrine::ORM::Mappings;
/**
* Represents a one-to-many mapping.
*
* NOTE: One-to-many mappings can currently not be uni-directional (one -> many).
* They must either be bidirectional (one <-> many) or unidirectional (many -> one).
* In other words, the many-side MUST be the owning side and the one-side MUST be
* the inverse side.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
* @todo Rename to OneToManyMapping
*/
class Doctrine_Association_OneToMany extends Doctrine_Association
{
/** The target foreign key columns that reference the sourceKeyColumns. */
protected $_targetForeignKeyColumns;
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
//protected $_targetForeignKeyColumns;
/** The (typically primary) source key columns that are referenced by the targetForeignKeyColumns. */
protected $_sourceKeyColumns;
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
//protected $_sourceKeyColumns;
/** This maps the target foreign key columns to the corresponding (primary) source key columns. */
protected $_targetForeignKeysToSourceKeys;
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
//protected $_targetForeignKeysToSourceKeys;
/** This maps the (primary) source key columns to the corresponding target foreign key columns. */
protected $_sourceKeysToTargetForeignKeys;
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
//protected $_sourceKeysToTargetForeignKeys;
/** Whether to delete orphaned elements (removed from the collection) */
protected $_deleteOrphans = false;
/**
* Constructor.
* Creates a new OneToManyMapping.
*
* @param array $mapping The mapping info.
*/
public function __construct(array $mapping)
{
parent::__construct($mapping);
// one side in one-many can currently never be owning side, we may support that later
$this->_isOwningSide = false;
}
/**
* Whether orphaned elements (removed from the collection) should be deleted.
*
* @return boolean TRUE if orphaned elements should be deleted, FALSE otherwise.
*/
public function shouldDeleteOrphans()
{
return $this->_deleteOrphans;
}
/**
* Whether the association is one-to-many.
*
* @return boolean TRUE if the association is one-to-many, FALSE otherwise.
* @override
*/
public function isOneToMany()
{
return true;
}
}
?>
\ No newline at end of file
......@@ -83,9 +83,7 @@ class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
*/
public function save($id, $data, $lifeTime = false)
{
$lifeTime = $this->getLifeTime($lifeTime);
return (bool) apc_store($id, array($data, time()), $lifeTime);
return (bool) apc_store($id, $data, $lifeTime);
}
/**
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Cache_Driver');
/**
* Doctrine_Cache_Memcache
*
......@@ -80,15 +80,7 @@ class Doctrine_Cache_Memcache extends Doctrine_Cache_Driver
*/
public function fetch($id, $testCacheValidity = true)
{
$tmp = $this->_memcache->get($id);
if (is_array($tmp)) {
return $tmp[0];
} else if (is_string($tmp)) {
return $tmp;
}
return false;
return $this->_memcache->get($id);
}
/**
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Cache_Driver');
/**
* Doctrine_Cache_Xcache
*
......
This diff is collapsed.
......@@ -31,7 +31,7 @@
* @version $Revision$
* @link www.phpdoctrine.org
* @since 2.0
* @todo Rename to ClassMetadataFactory.
* @todo Rename to ClassDescriptorFactory.
*/
class Doctrine_ClassMetadata_Factory
{
......@@ -114,6 +114,7 @@ class Doctrine_ClassMetadata_Factory
// load metadata of subclasses
// -> child1 -> child2 -> $name
// Move down the hierarchy of parent classes, starting from the topmost class
$parent = $class;
foreach ($parentClasses as $subclassName) {
$subClass = new Doctrine_ClassMetadata($subclassName, $this->_em);
......@@ -121,7 +122,7 @@ class Doctrine_ClassMetadata_Factory
$this->_addInheritedFields($subClass, $parent);
$this->_addInheritedRelations($subClass, $parent);
$this->_loadMetadata($subClass, $subclassName);
if ($parent->getInheritanceType() == Doctrine::INHERITANCE_TYPE_SINGLE_TABLE) {
if ($parent->isInheritanceTypeSingleTable()) {
$subClass->setTableName($parent->getTableName());
}
$classes[$subclassName] = $subClass;
......@@ -132,15 +133,17 @@ class Doctrine_ClassMetadata_Factory
/**
* Adds inherited fields to the subclass mapping.
*
* @param unknown_type $subClass
* @param unknown_type $parentClass
* @param Doctrine::ORM::Mapping::ClassMetadata $subClass
* @param Doctrine::ORM::Mapping::ClassMetadata $parentClass
* @return void
*/
protected function _addInheritedFields($subClass, $parentClass)
{
foreach ($parentClass->getFieldMappings() as $fieldName => $mapping) {
$fullName = "$name as " . $parentClass->getFieldName($name);
$mapping['inherited'] = true;
$subClass->mapField($mapping);
if ( ! isset($mapping['inherited'])) {
$mapping['inherited'] = $parentClass->getClassName();
}
$subClass->addFieldMapping($fieldName, $mapping);
}
}
......@@ -152,8 +155,8 @@ class Doctrine_ClassMetadata_Factory
*/
protected function _addInheritedRelations($subClass, $parentClass)
{
foreach ($parentClass->getRelationParser()->getRelationDefinitions() as $name => $definition) {
$subClass->getRelationParser()->addRelationDefinition($name, $definition);
foreach ($parentClass->getAssociationMappings() as $fieldName => $mapping) {
$subClass->addAssociationMapping($name, $mapping);
}
}
......
......@@ -83,7 +83,7 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
*
* @var Doctrine::ORM::Mapping::AssociationMapping
*/
protected $_associationMapping;
protected $_association;
/**
* The name of the column that is used for collection key mapping.
......@@ -99,8 +99,6 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
*/
//protected static $null;
protected $_mapping;
/**
* The EntityManager.
*
......@@ -261,10 +259,10 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
*
* @return void
*/
public function setReference(Doctrine_Entity $entity, $relation)
public function setReference(Doctrine_Entity $entity, Doctrine_Association $relation)
{
$this->_owner = $entity;
//$this->relation = $relation;
$this->_association = $relation;
/*if ($relation instanceof Doctrine_Relation_ForeignKey ||
$relation instanceof Doctrine_Relation_LocalKey) {
......@@ -304,6 +302,12 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
$removed = $this->_data[$key];
unset($this->_data[$key]);
//TODO: Register collection as dirty with the UoW if necessary
//$this->_em->getUnitOfWork()->scheduleCollectionUpdate($this);
//TODO: delete entity if shouldDeleteOrphans
/*if ($this->_association->isOneToMany() && $this->_association->shouldDeleteOrphans()) {
$this->_em->delete($removed);
}*/
return $removed;
}
......@@ -323,7 +327,7 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
*
* @param string $name
* @since 1.0
* @return void
* @return mixed
*/
public function __unset($key)
{
......@@ -508,7 +512,7 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
throw new Doctrine_Record_Exception('Value variable in set is not an instance of Doctrine_Entity.');
}
// Neither Maps nor Lists allow duplicates, both are Sets
// TODO: Really prohibit duplicates?
if (in_array($value, $this->_data, true)) {
return false;
}
......@@ -956,7 +960,7 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
public function mapElements($lambda) {
$result = array();
foreach ($this->_data as $key => $entity) {
list($key, $value) = $lambda($key, $entity);
list($key, $value) = each($lambda($key, $entity));
$result[$key] = $value;
}
return $result;
......@@ -969,14 +973,20 @@ class Doctrine_Collection implements Countable, IteratorAggregate, Serializable,
*/
public function clear()
{
$this->_data = array();
//TODO: Register collection as dirty with the UoW if necessary
//TODO: If oneToMany() && shouldDeleteOrphan() delete entities
/*if ($this->_association->isOneToMany() && $this->_association->shouldDeleteOrphans()) {
foreach ($this->_data as $entity) {
$this->_em->delete($entity);
}
}*/
$this->_data = array();
}
private function _changed()
{
/*if ( ! $this->_em->getUnitOfWork()->isCollectionScheduledForUpdate($this)) {
$this->_em->getUnitOfWork()->scheduleCollectionUpdate($this);
}*/
}*/
}
}
......@@ -932,7 +932,7 @@ abstract class Doctrine_Connection
*/
public function lastInsertId($table = null, $field = null)
{
return $this->sequence->lastInsertId($table, $field);
return $this->getSequenceManager()->lastInsertId($table, $field);
}
/**
......
......@@ -160,6 +160,8 @@ class Doctrine_Connection_UnitOfWork
foreach ($commitOrder as $class) {
$this->_executeInserts($class);
}
foreach ($commitOrder as $class) {
$this->_executeUpdates($class);
}
......@@ -268,7 +270,7 @@ class Doctrine_Connection_UnitOfWork
}
// add dependency
$otherNode = $this->_commitOrderCalculator->getNodeForKey($targetClassName);
$node->before($otherNode);
$otherNode->before($node);
}
}
}
......
......@@ -27,7 +27,8 @@
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @version $Revision$
* @link www.phpdoctrine.org
* @since 1.0
* @since 1.0
* @todo Remove.
*/
class Doctrine_DataDict_Informix extends Doctrine_DataDict
{
......
......@@ -227,6 +227,26 @@ class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
return 'CONCAT(' . join(', ', (array) $args) . ')';
}
/**
* @TEST
*/
public function getVarcharDeclaration(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
}
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
......
This diff is collapsed.
......@@ -44,7 +44,7 @@ class Doctrine_EntityManager
* IMMEDIATE: Flush occurs automatically after each operation that issues database
* queries. No operations are queued.
*/
const FLUSHMODE_IMMEDIATE = 'immediated';
const FLUSHMODE_IMMEDIATE = 'immediate';
/**
* AUTO: Flush occurs automatically in the following situations:
* - Before any query executions (to prevent getting stale data)
......@@ -86,7 +86,7 @@ class Doctrine_EntityManager
/**
* The metadata factory, used to retrieve the metadata of entity classes.
*
* @var Doctrine_ClassMetadata_Factory
* @var Doctrine::ORM::Mapping::ClassMetadataFactory
*/
private $_metadataFactory;
......@@ -539,7 +539,8 @@ class Doctrine_EntityManager
}
} else {
foreach ($data as $field => $value) {
if ( ! $entity->contains($field) || $entity->_internalGetField($field) === null) {
$currentValue = $entity->get($field);
if ( ! isset($currentValue) || $entity->_internalGetField($field) === null) {
$entity->_internalSetField($field, $value);
}
}
......
......@@ -72,7 +72,7 @@ abstract class Doctrine_EntityPersister_Abstract
private $_nullObject;
/**
* Constructs a new persister.
* Constructs a new EntityPersister.
*/
public function __construct(Doctrine_EntityManager $em, Doctrine_ClassMetadata $classMetadata)
{
......@@ -83,37 +83,78 @@ abstract class Doctrine_EntityPersister_Abstract
$this->_nullObject = Doctrine_Null::$INSTANCE;
}
/**
* Inserts an entity.
*
* @param Doctrine::ORM::Entity $entity The entity to insert.
* @return void
*/
public function insert(Doctrine_Entity $entity)
{
$insertData = array();
$dataChangeSet = $entity->_getDataChangeSet();
$class = $entity->getClass();
$referenceChangeSet = $entity->_getReferenceChangeSet();
foreach ($referenceChangeSet as $field => $change) {
list($old, $new) = each($change);
$assocMapping = $entity->getClass()->getAssociationMapping($field);
if ($assocMapping->isOneToOne()) {
if ($assocMapping->isInverseSide()) {
//echo "INVERSE!";
continue; // ignore inverse side
}
foreach ($assocMapping->getSourceToTargetKeyColumns() as $localColumn => $foreignColumn) {
//echo "$localColumn -- $foreignColumn<br/>";
//$insertData[$localColumn] = 1; //FIX
}
// ... set the foreign key column to the id of the related entity ($new)
$assocMapping = $class->getAssociationMapping($field);
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
//echo "NOT TO-ONE OR INVERSE!";
continue;
}
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
//TODO: What if both join columns (local/foreign) are just db-only
// columns (no fields in models) ? Currently we assume the foreign column
// is mapped to a field in the foreign entity.
$insertData[$sourceColumn] = $new->_internalGetField(
$new->getClass()->getFieldName($targetColumn)
);
}
//...
}
foreach ($dataChangeSet as $field => $change) {
$insertData[$entity->getClass()->getColumnName($field)] = current($change);
}
$this->_prepareData($entity, $insertData, true);
//TODO: perform insert
$this->_conn->insert($entity->getClass()->getTableName(), $insertData);
$this->_conn->insert($class->getTableName(), $insertData);
//TODO: if IDENTITY pk, assign it
if ($class->isIdGeneratorIdentity()) {
//TODO: Postgres IDENTITY columns (SERIAL) use a sequence, so we need to pass the
// sequence name to lastInsertId().
$entity->_assignIdentifier($this->_conn->lastInsertId());
}
}
/*protected function _fillJoinColumns($entity, array &$data)
{
$referenceChangeSet = $entity->_getReferenceChangeSet();
foreach ($referenceChangeSet as $field => $change) {
list($old, $new) = each($change);
$assocMapping = $entity->getClass()->getAssociationMapping($field);
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
//echo "NOT TO-ONE OR INVERSE!";
continue;
}
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
//TODO: What if both join columns (local/foreign) are just db-only
// columns (no fields in models) ? Currently we assume the foreign column
// is mapped to a field in the foreign entity.
$insertData[$sourceColumn] = $new->_internalGetField(
$new->getClass()->getFieldName($targetColumn)
);
}
}
}*/
/**
* Updates an entity.
*
* @param Doctrine::ORM::Entity $entity The entity to update.
* @return void
*/
public function update(Doctrine_Entity $entity)
{
$dataChangeSet = $entity->_getDataChangeSet();
......@@ -134,6 +175,12 @@ abstract class Doctrine_EntityPersister_Abstract
//TODO: perform update
}
/**
* Deletes an entity.
*
* @param Doctrine::ORM::Entity $entity The entity to delete.
* @return void
*/
public function delete(Doctrine_Entity $entity)
{
//TODO: perform delete
......@@ -177,6 +224,9 @@ abstract class Doctrine_EntityPersister_Abstract
return $this->_classMetadata;
}
/**
* @todo Move to ClassMetadata?
*/
public function getFieldNames()
{
if ($this->_fieldNames) {
......@@ -186,6 +236,9 @@ abstract class Doctrine_EntityPersister_Abstract
return $this->_fieldNames;
}
/**
* @todo Move to ClassMetadata?
*/
public function getOwningClass($fieldName)
{
return $this->_classMetadata;
......@@ -193,6 +246,7 @@ abstract class Doctrine_EntityPersister_Abstract
/**
* Callback that is invoked during the SQL construction process.
* @todo Move to ClassMetadata?
*/
public function getCustomJoins()
{
......@@ -201,6 +255,7 @@ abstract class Doctrine_EntityPersister_Abstract
/**
* Callback that is invoked during the SQL construction process.
* @todo Move to ClassMetadata?
*/
public function getCustomFields()
{
......@@ -213,7 +268,7 @@ abstract class Doctrine_EntityPersister_Abstract
*
* @return array
*/
protected function _convertFieldToColumnNames(array $fields, Doctrine_ClassMetadata $class)
/*protected function _convertFieldToColumnNames(array $fields, Doctrine_ClassMetadata $class)
{
$converted = array();
foreach ($fields as $fieldName => $value) {
......@@ -221,65 +276,52 @@ abstract class Doctrine_EntityPersister_Abstract
}
return $converted;
}
}*/
/**
* Returns an array of modified fields and values with data preparation
* adds column aggregation inheritance and converts Records into primary key values
*
* @param array $array
* @return array
* @return void
* @todo Move to EntityPersister. There call _getChangeSet() and apply this logic.
*/
public function prepareData(array $data = array())
protected function _prepareData($entity, array &$result, $isInsert = false)
{
$dataSet = array();
$modifiedFields = $fields;
foreach ($data as $field => $value) {
$type = $this->_classMetadata->getTypeOfField($field);
foreach ($entity->_getDataChangeSet() as $field => $change) {
list ($oldVal, $newVal) = each($change);
$type = $entity->getClass()->getTypeOfField($field);
$columnName = $entity->getClass()->getColumnName($field);
if ($value === Doctrine_Null::$INSTANCE) {
$dataSet[$field] = null;
if ($newVal === Doctrine_Null::$INSTANCE) {
$result[$columnName] = null;
continue;
}
switch ($type) {
case 'array':
case 'object':
$dataSet[$field] = serialize($value);
$result[$columnName] = serialize($newVal);
break;
case 'gzip':
$dataSet[$field] = gzcompress($value, 5);
$result[$columnName] = gzcompress($newVal, 5);
break;
case 'boolean':
$dataSet[$field] = $this->_em->getConnection()
->convertBooleans($value);
$result[$columnName] = $this->_em->getConnection()->convertBooleans($newVal);
break;
case 'enum':
$dataSet[$field] = $this->_class->enumIndex($field, $value);
break;
default:
$dataSet[$field] = $value;
$result[$columnName] = $newVal;
}
}
// @todo cleanup
// populates the discriminator field in Single & Class Table Inheritance
if ($this->_classMetadata->getInheritanceType() == Doctrine_ClassMetadata::INHERITANCE_TYPE_JOINED ||
$this->_class->getInheritanceType() == Doctrine_ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE) {
$discCol = $this->_classMetadata->getInheritanceOption('discriminatorColumn');
$discMap = $this->_classMetadata->getInheritanceOption('discriminatorMap');
$old = $this->get($discCol, false);
$discValue = array_search($this->_entityName, $discMap);
if ((string) $old !== (string) $discValue || $old === null) {
$dataSet[$discCol] = $discValue;
//$this->_data[$discCol] = $discValue;
}
// @todo Cleanup
// populates the discriminator column on insert in Single & Class Table Inheritance
if ($isInsert && ($entity->getClass()->isInheritanceTypeJoined() ||
$entity->getClass()->isInheritanceTypeSingleTable())) {
$discColumn = $entity->getClass()->getInheritanceOption('discriminatorColumn');
$discMap = $entity->getClass()->getInheritanceOption('discriminatorMap');
$result[$discColumn] = array_search($this->_entityName, $discMap);
}
return $dataSet;
}
......
......@@ -30,58 +30,53 @@
* @since 2.0
*/
class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_Abstract
{
//protected $_columnNameFieldNameMap = array();
{
/**
* Inserts an entity that is part of a Class Table Inheritance hierarchy.
*
* @param Doctrine_Entity $record record to be inserted
* @return boolean
* @override
*/
protected function _doInsert(Doctrine_Entity $record)
public function insert(Doctrine_Entity $entity)
{
$class = $this->_classMetadata;
$conn = $this->_conn;
$dataSet = $this->_groupFieldsByDefiningClass($record);
$class = $entity->getClass();
$dataSet = array();
$this->_prepareData($entity, $dataSet, true);
$dataSet = $this->_groupFieldsByDefiningClass($class, $dataSet);
$component = $class->getClassName();
$classes = $class->getParentClasses();
array_unshift($classes, $component);
try {
$conn->beginInternalTransaction();
$identifier = null;
foreach (array_reverse($classes) as $k => $parent) {
$parentClass = $conn->getClassMetadata($parent);
if ($k == 0) {
$identifierType = $parentClass->getIdentifierType();
if ($identifierType == Doctrine::IDENTIFIER_AUTOINC) {
$identifier = null;
foreach (array_reverse($classes) as $k => $parent) {
$parentClass = $this->_em->getClassMetadata($parent);
if ($k == 0) {
if ($parentClass->isIdGeneratorIdentity()) {
$this->_insertRow($parentClass->getTableName(), $dataSet[$parent]);
$identifier = $this->_conn->lastInsertId();
} else if ($parentClass->isIdGeneratorSequence()) {
$seq = $entity->getClassMetadata()->getTableOption('sequenceName');
if ( ! empty($seq)) {
$id = $this->_conn->getSequenceManager()->nextId($seq);
$identifierFields = $parentClass->getIdentifier();
$dataSet[$parent][$identifierFields[0]] = $id;
$this->_insertRow($parentClass->getTableName(), $dataSet[$parent]);
$identifier = $conn->sequence->lastInsertId();
} else if ($identifierType == Doctrine::IDENTIFIER_SEQUENCE) {
$seq = $record->getClassMetadata()->getTableOption('sequenceName');
if ( ! empty($seq)) {
$id = $conn->sequence->nextId($seq);
$identifierFields = (array)$parentClass->getIdentifier();
$dataSet[$parent][$identifierFields[0]] = $id;
$this->_insertRow($parentClass->getTableName(), $dataSet[$parent]);
}
} else {
throw new Doctrine_Mapper_Exception("Unsupported identifier type '$identifierType'.");
}
$record->assignIdentifier($identifier);
} else {
foreach ((array) $record->identifier() as $id => $value) {
$dataSet[$parent][$parentClass->getColumnName($id)] = $value;
}
$this->_insertRow($parentClass->getTableName(), $dataSet[$parent]);
throw new Doctrine_Mapper_Exception("Unsupported identifier type '$identifierType'.");
}
$entity->_assignIdentifier($identifier);
} else {
foreach ($entity->_identifier() as $id => $value) {
$dataSet[$parent][$parentClass->getColumnName($id)] = $value;
}
$this->_insertRow($parentClass->getTableName(), $dataSet[$parent]);
}
$conn->commit();
} catch (Exception $e) {
$conn->rollback();
throw $e;
}
return true;
......@@ -255,29 +250,26 @@ class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_A
*
* @return array
*/
protected function _groupFieldsByDefiningClass(Doctrine_Entity $record)
protected function _groupFieldsByDefiningClass(Doctrine_ClassMetadata $class, array $fields)
{
$conn = $this->_conn;
$classMetadata = $this->_classMetadata;
$dataSet = array();
$component = $classMetadata->getClassName();
$array = $record->getPrepared();
$component = $class->getClassName();
$classes = array_merge(array($component), $classMetadata->getParentClasses());
$classes = array_merge(array($component), $class->getParentClasses());
foreach ($classes as $class) {
$dataSet[$class] = array();
$parentClassMetadata = $conn->getClassMetadata($class);
foreach ($parentClassMetadata->getColumns() as $columnName => $definition) {
if ((isset($definition['primary']) && $definition['primary'] === true) ||
(isset($definition['inherited']) && $definition['inherited'] === true)) {
$parentClassMetadata = $this->_em->getClassMetadata($class);
foreach ($parentClassMetadata->getFieldMappings() as $fieldName => $mapping) {
if ((isset($mapping['id']) && $mapping['id'] === true) ||
(isset($mapping['inherited']) && $mapping['inherited'] === true)) {
continue;
}
$fieldName = $classMetadata->getFieldName($columnName);
if ( ! array_key_exists($fieldName, $array)) {
if ( ! array_key_exists($fieldName, $fields)) {
continue;
}
$dataSet[$class][$columnName] = $array[$fieldName];
$columnName = $parentClassMetadata->getColumnName($fieldName);
$dataSet[$class][$columnName] = $fields[$fieldName];
}
}
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Hook_Parser');
/**
* Doctrine_Hook_Equal
*
......@@ -28,7 +28,9 @@ Doctrine::autoload('Doctrine_Hook_Parser');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Can be removed?
* @deprecated
*/
class Doctrine_Hook_Equal extends Doctrine_Hook_Parser
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Hook_Parser_Complex');
/**
* Doctrine_Hook_Integer
*
......@@ -28,7 +28,9 @@ Doctrine::autoload('Doctrine_Hook_Parser_Complex');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Can be removed?
* @deprecated
*/
class Doctrine_Hook_Integer extends Doctrine_Hook_Parser_Complex
{
......
......@@ -28,7 +28,9 @@
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Can be removed?
* @deprecated
*/
abstract class Doctrine_Hook_Parser
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Hook_Parser');
/**
* Doctrine_Hook_Parser_Complex
*
......@@ -28,7 +28,9 @@ Doctrine::autoload('Doctrine_Hook_Parser');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Can be removed?
* @deprecated
*/
abstract class Doctrine_Hook_Parser_Complex extends Doctrine_Hook_Parser
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Hook_Parser');
/**
* Doctrine_Hook_WordLike
*
......@@ -28,7 +28,9 @@ Doctrine::autoload('Doctrine_Hook_Parser');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated
* @todo Can be removed?
*/
class Doctrine_Hook_WordLike extends Doctrine_Hook_Parser_Complex
{
......
......@@ -88,33 +88,51 @@ class Doctrine_Query_Production_Join extends Doctrine_Query_Production
return $sql . ' ON ' . $conditionExpression;
}
// We need to build the relationship conditions. Retrieving AssociationMapping
$queryComponent = $this->_rangeVariableDeclaration->getQueryComponent();
$relationColumns = $queryComponent['relation']->getSourceToTargetKeyColumns();
$relationConditionExpression = '';
// We have an array('localColumn' => 'foreignColumn', ...) here
foreach ($relationColumns as $localColumn => $foreignColumn) {
// leftExpression = rightExpression
// Defining leftExpression
$leftExpression = $conn->quoteIdentifier(
$parserResult->getTableAliasFromComponentAlias($queryComponent['parent']) . '.' . $localColumn
);
// Defining rightExpression
$rightExpression = $conn->quoteIdentifier(
$parserResult->getTableAliasFromComponentAlias(
$this->_rangeVariableDeclaration->getIdentificationVariable()
) . '.' . $foreignColumn
);
// Building the relation
$relationConditionExpression .= (($relationConditionExpression != '') ? ' AND ' : '')
. $leftExpression . ' = ' . $rightExpression;
}
return $sql . ' ON ' . $relationConditionExpression . ' AND (' . $conditionExpression . ')';
// We need to build the join conditions. Retrieving AssociationMapping
$queryComponent = $this->_rangeVariableDeclaration->getQueryComponent();
$association = $queryComponent['relation'];
$joinColumns = array();
if ($association->isOneToMany() || $association->isOneToOne()) {
if ($association->isInverseSide()) {
// joinColumns are found on the other (owning) side
$targetClass = $this->_em->getClassMetadata($association->getTargetEntityName());
$joinColumns = $targetClass->getAssociationMapping($association->getMappedByFieldName())
->getTargetToSourceKeyColumns();
} else {
$joinColumns = $association->getSourceToTargetKeyColumns();
}
} else {
//TODO: many-many
}
$relationConditionExpression = '';
// We have an array('localColumn' => 'foreignColumn', ...) here
foreach ($joinColumns as $localColumn => $foreignColumn) {
// leftExpression = rightExpression
// Defining leftExpression
$leftExpression = $conn->quoteIdentifier(
$parserResult->getTableAliasFromComponentAlias($queryComponent['parent']) . '.' . $localColumn
);
// Defining rightExpression
$rightExpression = $conn->quoteIdentifier(
$parserResult->getTableAliasFromComponentAlias(
$this->_rangeVariableDeclaration->getIdentificationVariable()
) . '.' . $foreignColumn
);
// Building the relation
$relationConditionExpression .= (($relationConditionExpression != '') ? ' AND ' : '')
. $leftExpression . ' = ' . $rightExpression;
}
$sql .= ' ON ' . $relationConditionExpression;
$sql .= empty($conditionExpression) ? '' : ' AND (' . $conditionExpression . ')';
return $sql;
}
......
......@@ -52,7 +52,7 @@ class Doctrine_Query_Production_JoinVariableDeclaration extends Doctrine_Query_P
public function buildSql()
{
return $this->_join->buildSql() . ' ' . (isset($this->_indexby) ? $this->_indexby->buildSql() . ' ' : '');
return $this->_join->buildSql() . (isset($this->_indexby) ? $this->_indexby->buildSql() . ' ' : '');
}
......
......@@ -18,7 +18,9 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Exception');
#namespace Doctrine::ORM::Exceptions;
/**
* Doctrine_RawSql_Exception
*
......@@ -28,7 +30,8 @@ Doctrine::autoload('Doctrine_Exception');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Rename to NativeSqlException or maybe remove.
*/
class Doctrine_RawSql_Exception extends Doctrine_Exception
{ }
\ No newline at end of file
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Exception');
/**
* Doctrine_Exception
*
......@@ -28,7 +28,8 @@ Doctrine::autoload('Doctrine_Exception');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated Remove.
*/
class Doctrine_Record_Exception extends Doctrine_Exception
{ }
\ No newline at end of file
......@@ -29,7 +29,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 1298 $
* @version $Revision: 1298 $
* @deprecated Remove.
*/
abstract class Doctrine_Record_Filter
{
......
......@@ -28,7 +28,9 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 1298 $
* @version $Revision: 1298 $
* @todo Remove.
* @deprecated
*/
class Doctrine_Record_Filter_Compound extends Doctrine_Record_Filter
{
......
......@@ -29,7 +29,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 1298 $
* @version $Revision: 1298 $
* @deprecated Remove.
*/
class Doctrine_Record_Filter_Standard extends Doctrine_Record_Filter
{
......
......@@ -28,7 +28,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$
* @link www.phpdoctrine.org
* @since 1.0
* @since 1.0
* @todo Rename. Move. Reimpl?
*/
abstract class Doctrine_Record_Generator
{
......
......@@ -28,7 +28,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated Remove.
*/
class Doctrine_Record_Iterator extends ArrayIterator
{
......
......@@ -28,7 +28,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated Remove.
*/
class Doctrine_Record_Listener implements Doctrine_Record_Listener_Interface
{
......
......@@ -18,7 +18,6 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Access');
/**
* Doctrine_Record_Listener_Chain
......@@ -31,7 +30,9 @@ Doctrine::autoload('Doctrine_Access');
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated
* @todo Remove
*/
class Doctrine_Record_Listener_Chain extends Doctrine_Access implements Doctrine_Record_Listener_Interface
{
......
......@@ -28,7 +28,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated Remove.
*/
interface Doctrine_Record_Listener_Interface
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Record_Exception');
/**
* Doctrine_Exception
*
......@@ -28,7 +28,8 @@ Doctrine::autoload('Doctrine_Record_Exception');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Deprecated. Remove
*/
class Doctrine_Record_State_Exception extends Doctrine_Record_Exception
{ }
\ No newline at end of file
......@@ -29,7 +29,8 @@
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated
*/
abstract class Doctrine_Relation implements ArrayAccess
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Relation');
/**
* Doctrine_Relation_Association
*
......@@ -30,7 +30,8 @@ Doctrine::autoload('Doctrine_Relation');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated
*/
class Doctrine_Relation_Association extends Doctrine_Relation
{
......
......@@ -28,7 +28,8 @@
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated
*/
class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
{
......
......@@ -29,7 +29,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated
*/
class Doctrine_Relation_ForeignKey extends Doctrine_Relation
{
......
......@@ -29,7 +29,8 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @version $Revision$
* @deprecated
*/
class Doctrine_Relation_LocalKey extends Doctrine_Relation
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Relation_Association');
/**
* Doctrine_Relation_Association_Self
*
......@@ -28,7 +28,8 @@ Doctrine::autoload('Doctrine_Relation_Association');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 1434 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated
*/
class Doctrine_Relation_Nest extends Doctrine_Relation_Association
{
......
......@@ -30,7 +30,8 @@
* @link www.phpdoctrine.org
* @since 1.0
* @todo Composite key support?
* @todo Remove. Association mapping needs a reimplementation.
* @todo Remove. Association mapping is being reimplemented.
* @deprecated
*/
class Doctrine_Relation_Parser
{
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Relation_Exception');
/**
* Doctrine_Relation_Parser_Exception
*
......@@ -28,7 +28,8 @@ Doctrine::autoload('Doctrine_Relation_Exception');
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @deprecated Remove.
*/
class Doctrine_Relation_Parser_Exception extends Doctrine_Relation_Exception
{ }
\ No newline at end of file
......@@ -83,7 +83,7 @@ class Doctrine_Sequence_Mysql extends Doctrine_Sequence
*/
public function lastInsertId($table = null, $field = null)
{
return $this->conn->getDbh()->lastInsertId();
return $this->conn->getPdo()->lastInsertId();
}
/**
......
......@@ -84,7 +84,7 @@ class Doctrine_Sequence_Sqlite extends Doctrine_Sequence
*/
public function lastInsertId($table = null, $field = null)
{
return $this->conn->getDbh()->lastInsertId();
return $this->conn->getPdo()->lastInsertId();
}
/**
......
......@@ -11,32 +11,54 @@ class Orm_EntityPersisterTest extends Doctrine_OrmTestCase
private $_persister; // SUT
private $_connMock;
private $_emMock;
private $_seqManagerMock;
protected function setUp() {
parent::setUp();
$this->_connMock = new Doctrine_ConnectionMock(array());
$this->_emMock = new Doctrine_EntityManagerMock($this->_connMock);
$this->_seqManagerMock = new Doctrine_SequenceMock($this->_connMock);
$this->_connMock->setDatabasePlatform(new Doctrine_DatabasePlatformMock());
$this->_connMock->setSequenceManager($this->_seqManagerMock);
$this->_persister = new Doctrine_EntityPersister_Standard(
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
}
public function testTest() {
public function testInsert() {
$user = new ForumUser();
$user->username = "romanb";
$user->avatar = new ForumAvatar();
$this->_persister->insert($user);
$this->_seqManagerMock->autoinc(); //fake identity column autoinc
$this->_persister->insert($user->avatar);
$inserts = $this->_connMock->getInserts();
//check
$this->assertEquals(1, count($inserts));
$this->assertEquals(0, $user->avatar->id);
$this->assertTrue(isset($inserts['forum_avatar']));
$this->assertEquals(1, count($inserts['forum_avatar']));
$this->assertTrue(empty($inserts['forum_avatar'][0]));
$this->_seqManagerMock->autoinc(); //fake identity column autoinc
$this->_persister->insert($user);
$inserts = $this->_connMock->getInserts();
//var_dump($inserts);
//check
$this->assertEquals(2, count($inserts));
$this->assertEquals(1, $user->id);
$this->assertTrue(isset($inserts['forum_user']));
$this->assertEquals(1, count($inserts['forum_user']));
$this->assertEquals(1, count($inserts['forum_user'][0]));
$this->assertEquals(3, count($inserts['forum_user'][0]));
//username column
$this->assertTrue(isset($inserts['forum_user'][0]['username']));
$this->assertEquals('romanb', $inserts['forum_user'][0]['username']);
//avatar_id join column
$this->assertTrue(isset($inserts['forum_user'][0]['avatar_id']));
$this->assertEquals(0, $inserts['forum_user'][0]['avatar_id']);
//dtype discriminator column
$this->assertTrue(isset($inserts['forum_user'][0]['dtype']));
$this->assertEquals('user', $inserts['forum_user'][0]['dtype']);
}
}
\ No newline at end of file
......@@ -172,7 +172,7 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
{
$this->assertSqlGeneration(
'SELECT u.id, a.id FROM CmsUser u LEFT JOIN u.articles a',
'SELECT cu.id AS cu__id, ca.id AS ca__id FROM cms_user cu LEFT JOIN cms_article ca ON ca.user_id = cu.id WHERE 1 = 1'
'SELECT cu.id AS cu__id, ca.id AS ca__id FROM cms_user cu LEFT JOIN cms_article ca ON cu.id = ca.user_id WHERE 1 = 1'
);
}
......
......@@ -126,6 +126,23 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
$this->assertEquals(0, count($this->_persisterMock->getDeletes()));
}
public function testCommitOrder()
{
$avatar = new ForumAvatar();
$this->_user->avatar = $avatar;
$this->_unitOfWork->save($this->_user); // save cascaded to avatar
$this->assertEquals(2, count($this->_persisterMock->getInserts())); // insert forced
$this->assertEquals(0, count($this->_persisterMock->getUpdates()));
$this->assertEquals(0, count($this->_persisterMock->getDeletes()));
// verify order of inserts()s
$inserts = $this->_persisterMock->getInserts();
$this->assertSame($avatar, $inserts[0]);
$this->assertSame($this->_user, $inserts[1]);
//...
}
public function testSavingSingleEntityWithSequenceIdGeneratorSchedulesInsert()
{
//...
......
......@@ -34,6 +34,11 @@ class Doctrine_SequenceMock extends Doctrine_Sequence
{
$this->_sequenceNumber = 0;
}
public function autoinc()
{
$this->_sequenceNumber++;
}
}
?>
\ No newline at end of file
......@@ -35,17 +35,16 @@ class CmsArticle extends Doctrine_Entity
'length' => 4
));
/*$mapping->hasMany('CmsComment as comments', array(
'local' => 'id', 'foreign' => 'article_id'));*/
$mapping->mapOneToMany(array(
'fieldName' => 'comments',
'targetEntity' => 'CmsComment',
));
/*$mapping->mapManyToOne(array(
'fieldName' => 'author',
$mapping->mapManyToOne(array(
'fieldName' => 'user',
'targetEntity' => 'CmsUser',
'joinColumns' => array('user_id' => 'id')
));*/
));
}
}
......@@ -17,5 +17,11 @@ class CmsPhonenumber extends Doctrine_Entity
'length' => 50,
'id' => true
));
$mapping->mapManyToOne(array(
'fieldName' => 'user',
'targetEntity' => 'CmsUser',
'joinColumns' => array('user_id' => 'id')
));
}
}
......@@ -35,21 +35,17 @@ class CmsUser extends Doctrine_Entity
'type' => 'string',
'length' => 255
));
/*$mapping->hasMany('CmsPhonenumber as phonenumbers', array(
'local' => 'id', 'foreign' => 'user_id'));
$mapping->hasMany('CmsArticle as articles', array(
'local' => 'id', 'foreign' => 'user_id'));*/
$mapping->mapOneToMany(array(
'fieldName' => 'phonenumbers',
'targetEntity' => 'CmsPhonenumber',
'mappedBy' => 'user'
));
$mapping->mapOneToMany(array(
'fieldName' => 'articles',
'targetEntity' => 'CmsArticle',
'mappedBy' => 'user'
));
}
......
......@@ -21,12 +21,6 @@ class ForumUser extends Doctrine_Entity
));
// register subclasses
$mapping->setSubclasses(array('ForumAdministrator'));
// the discriminator column
$mapping->mapField(array(
'fieldName' => 'dtype',
'type' => 'string',
'length' => 50
));
// column-to-field mapping
$mapping->mapField(array(
......@@ -46,6 +40,7 @@ class ForumUser extends Doctrine_Entity
'fieldName' => 'avatar',
'targetEntity' => 'ForumAvatar',
'joinColumns' => array('avatar_id' => 'id'),
'cascade' => array('save')
));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment