5
votes

I'm using Symfony 2.1.2.

I have two entities and define a [many-to-one (bidirectional)] (1) association between them. I don't want to use the primary key for the foreign key (referencedColumnName). I want to use another integer unique column: customer_no

/**
 * @ORM\Entity
 * @ORM\Table(name="t_myuser")
 */
class MyUser extends BaseEntity // provides an id (pk)
{
    /**
     * @ORM\ManyToOne(targetEntity="Customer", inversedBy="user")
     * @ORM\JoinColumn(name="customer_no", referencedColumnName="customer_no", nullable=false)
     */
    public $customer;
}

/**
 * @ORM\Entity
 * @ORM\Table(name="t_customer")
 */
class Customer extends BaseEntity // provides an id (pk)
{
    /**
     * @ORM\Column(type="integer", unique=true, nullable=false)
     */
    public $customer_no;

    /**
     * @ORM\OneToMany(targetEntity="MyUser", mappedBy="customer")
     */
    public $user;
}

When I try to persist a MyUser entity with an Customer entity, I get this error:

Notice: Undefined index: customer_no in ...\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php line 608

The schema on the db looks fine, these should be the important sql schema definitions:

CREATE UNIQUE INDEX UNIQ_B4905AC83CDDA96E ON t_customer (customer_no);
CREATE INDEX IDX_BB041B3B3CDDA96E ON t_myuser (customer_no);
ALTER TABLE t_myuser ADD CONSTRAINT FK_BB041B3B3CDDA96E FOREIGN KEY (customer_no) 
  REFERENCES t_customer (customer_no) NOT DEFERRABLE INITIALLY IMMEDIATE;

So there is definitely an index for customer_no

//update: I fix the inversedBy and mappedBy stuff, but this is not the problem.

(1) : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-bidirectional

1
Not sure if it has anything to do, but inversedBy and mappedBy should contain the name of the property in the other entity, not the name of the database tableCarlos Granados
It does not say the opposite. Look, it says mappedBy="product" where product is the name of the property in the Feature entity. And inversedBy="features", where features is the name of the property in the Product entity. It does not speak of table names anywhereCarlos Granados
I fix it, but this is not the problemtimaschew
Documentation of @JoinColumn states that referencedColumnName will be the primary key identifier of the joining table. So non-key column can not be referenced IMHO.Mun Mun Das

1 Answers

2
votes

@m2mdas:
Yes you're right, I thought it's possible because JPA (which has influence to doctrine) has this feature. The attribute referencedColumnName only for the case when your property does not match the table column.

Whatever, I found a solution by patching the BasicEntityPersister.php, see here the gist on github: https://gist.github.com/3800132

the solution is to add the property/field name and value for the mapping column. This information is already there but not bound to the right place. It have to be added to the $newValId arrray this way:

$fieldName = $targetClass->getFieldName($targetColumn);
$newValId[$fieldName] = $targetClass->getFieldValue($newVal, $fieldName);

It only works for ManyToOne reference. ManyToMany doesn't work.
For ManyToOne I test it with already existing entities. You can test it, too:

change the doctrine annotation in tests/Doctrine/Tests/Models/Legacy/LegacyArticle.php
from

@JoinColumn(name="iUserId", referencedColumnName="iUserId")

to

@JoinColumn(name="username", referencedColumnName="sUsername")