[DDC-250] ArrayCollection Key Column @indexBy Created: 12/Jan/10  Updated: 29/Dec/13  Resolved: 05/Feb/11

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

Type: New Feature Priority: Minor
Reporter: Michael Ridgway Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 1
Labels: None

Issue Links:
Dependency
depends on DDC-1018 INDEX BY does not work in JOIN clauses Resolved
Reference
relates to DDC-213 Persist order of collections Open

 Description   

To be honest I feel like I saw this mentioned somewhere, but after looking around I couldn't find it, so I'll just post this anyway.

I'd like the ability to set a property as the associative key on ArrayCollections. This functionality could probably be done in a PostLoad by iterating over the objects, but it seems like ArrayCollection should be able to handle this functionality already, it's just a matter of modifying the mapper/parser.

Example:

/**
 * @Entity
 */
class Object
{
//... $id column and anything else ...
    /**
     * @OneToMany(targetEntity="Param", mappedBy="object")
     */
    protected $params;
//...
    public function getParam($name)
    {
         return $this->params[$name];
    }
}

/**
 * @Entity
 */
class Param
{
    /**
     * @ManyToOne(targetEntity="Object")
     * @JoinColumn(name="object_id", referencedColumnName="id", nullable="false")
     */
    protected $object;
    /**
     * @Column(type="string")
     */
    protected $name;
    /**
     * @Column(type="string")
     */
    protected $value;
}

If you were able to specify an ArrayCollection key column then you would be able to have functions like getParam without having to loop over the objects in the collection. Something like:

 @OneToMany(targetEntity="Param", mappedBy="object", collectionKey="name") 


 Comments   
Comment by Marijn Huizendveld [ 19/Apr/10 ]

As much as I would like this I doubt it is possible feasible. Imagine the name column of your Param object not being unique for you your linked Object..? How could the ArrayCollection know which instance to add to the collection and which one not?

Comment by Michael Ridgway [ 19/Apr/10 ]

You are absolutely correct. There is no way to ensure the uniqueness of the collection elements. This is something that would have to be ensured in the domain model and shouldn't have anything to do with Doctrine.

It will certainly work to loop through the collection on PostLoad (once DDC-54 is implemented). For now, I just set the keys the first time I call getParam().

I suppose I should close this (I forgot it was still open).

Comment by Michael Ridgway [ 06/Oct/10 ]

I just noticed that DQL has an INDEX BY keyword to be able to do this during a DQL query. Is this something that could then be possible to set in a oneToMany or manyToMany? It seems like most of the groundwork for being able to do this is already done.

Comment by Benjamin Eberlei [ 24/Dec/10 ]

Example code:

<?php

class Article
{
    /** @Id @Column(type="integer") @GeneratedValue */
    public $id;

    /** @Column(type="string")
    public $headline;

    /**
     * @OneToMany(targetEntity="Translation", mappedBy="article")
     * @IndexBy("language")
     */
    public $translations;
}

class Translation
{
    /**
     * @Id @Column(type="string")
     */
    public $language;

    /**
     * @Id @ManyToOne(targetEntity="Article", inversedBy="translations")
     */
    public $article;

    /**
     * @Column(type="string")
     */
    public $headline;
}


$article = $em->find("Article", 1);
$article->translations["en"]->headlinle;

In this case @IndexBy uses the Translation::$language as key for the collection.

Comment by Benjamin Eberlei [ 24/Dec/10 ]

Schedule for 2.1

Comment by Benjamin Eberlei [ 05/Feb/11 ]

This is now in master https://github.com/doctrine/doctrine2/commit/7390030854cdb4b775f6f11f83c970ab2705e924

Syntax is:

@ManyToMany(targetEntity="OtherEntity", indexBy="foreignField")
@OneToMany(targetEntity="OtherEntity", indexBy="foreignField")
<many-to-many index-by="foreignField" />
manyToMany:
  indexBy: foreignField
Comment by Benjamin Eberlei [ 11/Oct/12 ]

A related Github Pull-Request [GH-470] was opened
https://github.com/doctrine/doctrine2/pull/470

Comment by Doctrine Bot [ 29/Dec/13 ]

A related Github Pull-Request [GH-470] was closed:
https://github.com/doctrine/dbal/pull/470

Generated at Fri Oct 24 13:04:22 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.