dj_thossi
dj_thossi

Reputation: 804

doctrine2 mapping overwrite inherited inversedBy field from MappedSuperclass

another question. I have a abstract BaseLog Entity which keeps the association to my user. In addition I have 2 Entities (FooLog & BarLog) which extend BaseLog. In addition I have my User Entity which are suppose to hold two associations to Log. One for FooLog and one for BarLog. Here is my issue. I get error messages because I don't know how to overwrite BaseLog's inversedBy field in extending Entity. Could you please help me.

Because I think my explanation is not really good, here the Set up of my entities.

BaseLog

/** @ORM\MappedSuperclass */
abstract class BaseLog {
  /**
   * @ORM\ManyToOne(targetEntity="User", inversedBy="logs")
   * @ORM\JoinColumns({
   *   @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
   * })
   */
  private $user;
}

FooLog

/** @ORM\Entity */
class FooLog extends BaseLog {
  // Some additional fields
}

BarLog

/** @ORM\Entity */
class BarLog extends BaseLog {
  // Some additional fields
}

User

/** @ORM\Entity */
class User {
  /**
   * @ORM\OneToMany(targetEntity="FooLog", mappedBy="user", cascade={"persist"})
   */
  private $fooLogs;

  /**
   * @ORM\OneToMany(targetEntity="BarLog", mappedBy="user", cascade={"persist"})
   */
  private $barLogs;
}

How do I have to overwrite BaseLog's inversedBy in FooLog & BarLog.

I get several Mapping error on this set up: BaseLog

Please help me to get my mapping sorted.

Upvotes: 8

Views: 6035

Answers (4)

Sumit
Sumit

Reputation: 2387

The correct way to do this (since Doctrine 2.3) is using AssociationOverrides.

Remove inversedBy="logs" from BaseLog class - since a mapped super class doesn't represent a real entity anyway - and then override it in subclasses. Here's how that should look:

BaseLog

/** @ORM\MappedSuperclass */
abstract class BaseLog {
  /**
   * @ORM\ManyToOne(targetEntity="User")
   * @ORM\JoinColumns({
   *   @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
   * })
   */
  private $user;
}

FooLog

/**
 * @ORM\Entity */
 * @ORM\AssociationOverrides({
 *     @ORM\AssociationOverride(name="user", inversedBy="fooLogs")
 * })
 */
class FooLog extends BaseLog {
  // Some additional fields
}

BarLog

/**
 * @ORM\Entity */
 * @ORM\AssociationOverrides({
 *     @ORM\AssociationOverride(name="user", inversedBy="barLogs")
 * })
 */
class BarLog extends BaseLog {
  // Some additional fields
}

name= in @ORM\AssociationOverride represents the field you want to override from the mapped super class.

Upvotes: 2

l3l0
l3l0

Reputation: 3393

IIRC there was not good way to override mappings in older versions of Doctrine. In Doctrine >= 2.2 there is something called association override so maybe you can use it.

BTW Why do you not want move associations from base to concrete classes and define valid inversedBy then ?

Upvotes: 1

Vladatos
Vladatos

Reputation: 154

I had similar issue with single inheritance. I resolved this by defining same association in both entity classes (parent and inherited) but with different name. In your case you can try this:

    /** @ORM\Entity */
class FooLog extends BaseLog {
  /**
   * @ORM\ManyToOne(targetEntity="User", inversedBy="foologs")
   * @ORM\JoinColumns({
   *   @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
   * })
   */
   private $user;
}

and in class BarLog:

/** @ORM\Entity */
    class BarLog extends BaseLog {
      /**
       * @ORM\ManyToOne(targetEntity="User", inversedBy="barlogs")
       * @ORM\JoinColumns({
       *   @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
       * })
       */
       private $bar_user;
    }

Notice different name ($bar_user). You also have to define foologs and barlogs properties in user entity. This removes doctrine validation errors.

Upvotes: 4

Ryan
Ryan

Reputation: 5036

I have struggled with the same issue using Single Table Inheritance. As far as I can tell there isn't a solution to it. Even though inversedBy is considered compulsory, it seems you can get away with ignoring it. However, as the Doctrine docs suggest the performance deteriorates rapidly.

@AssociationOverride doesn't help, because you can't modify association definitions, only database column properties.

I've tried a number of options, none of which are satisfactory.

Update: I still haven't been able to find any solution to these sorts of errors when running app/console doctrine:schema:validate.

[Mapping]  FAIL - The entity-class 'Acme\AcmeBundle\Entity\CourseLocation' mapping is invalid:
* The field Acme\AcmeBundle\Entity\CourseLocation#facilitators is on the inverse side of a bi-directional relationship, but the specified mappedBy association on the target-entity Acme\AcmeBundle\Entity\CourseFacilitatorResponsibility#courseLocation does not contain the required 'inversedBy' attribute.

In this instance CourseFacilitatorResponsibility is a sub-class (with single table inheritance) of CourseResponsibility. CourseLocation refers to multiple CourseResponsibility entities. I think uni-directional associations is the only way around it.

Upvotes: 3

Related Questions