Thursday, March 31, 2011

How can I allow Duplicate Records in a Doctrine Collection

I'm hoping there are some fellow doctrine users out there.
Here is a simplified YAML of my relationships:

Collection:
  columns:
    id:           { type: integer(4), notnull: true, primary: true, autoincrement: true }
    name:         { type: string(255), notnull: true, unique: true }
  relations:
    Items:
      class: Item
      refClass: CollectionItem
      foreignAlias: Collections
      type: many
      foreignType: many

Item:
  columns:
    id:   { type: integer(4), notnull: true, primary: true, autoincrement: true }
    name: { type: string(255), notnull: true }

CollectionItem:
  columns:
    id:       { type: integer(4), notnull: true, primary: true, autoincrement: true }
    collection_id:  { type: integer(4) }
    item_id:  { type: integer(4) }
  relations:
    Collection:
      foreignAlias: CollectionItem
      foreignType: one
    Item:
      foreignAlias: CollectionItem
      foreignType: one

I want a collection to be able to hold many copies of the same item, but when I use the generated classes to load items like so:

$collection = Doctrine::getTable('Collection')->find(1);
$items = $collection->Items;

$items doesn't contain my duplicates. The generated sql seems to correctly return duplicate rows:

SELECT  i.id AS  i__id, i.name AS  i__name, c.id AS  c__id, c.collection_id AS  c__collection_id, c.item_id AS  c__item_id, FROM item i LEFT JOIN collection_item c ON i.id = c.item_id WHERE c.collection_id IN (?) - (1)

I know I can get around this my making specific dql queries instead but does anyone know if there is simple setting somewhere to allow the Items collection to have duplicates?

From stackoverflow
  • did you try:

    foreach($collection->Items as $item)
    {
        // do something with $item
    }
    

    if i recall correctly $collection->Items isn't a real array it's a object implementing ArrayAccess / ArrayIterator

  • In Doctrine you can't have duplicate objects. Each object retrieved from the database is stored only once in Doctrine. If you query for the same object twice you'll get a pointer the the same object you had already retrieved.

    You can clone the object and store it in your Doctrine_Collection, but that will actually create another row in the database when you save the collection.

  • you have to change the hydration mode to HYDRATE_SCALAR:

    This hydration mode creates a flat/rectangular result set that can contain duplicate data.

    $res = $q->execute(array(), Doctrine::HYDRATE_SCALAR);
    

    (or to HYDRATE_NONE)

    as stated in http://www.doctrine-project.org/documentation/manual/1_1/en/working-with-models#fetching-data

0 comments:

Post a Comment