2

I have many ads entities (MotorAds, RealestateAds, ElectronicsAds, ...) that share some attributes like title and description. In order to avoid redefining these attributes for each Ads entity, one can use the mapped superclass methods as follows:

<?php
/** @MappedSuperclass */
class MappedSuperclassAds{
    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255, nullable=false)
     */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text", nullable=false)
     */
    private $description;
}

Then, the inheritance will do the job.

Now, what is the problem? The problem is that each Ads entity is related to its entity that defines the list of users that added the ads to their favorites. To do that (the MotorsAds entity for example),

1.linking the MotorsAds entity to its MotorsFavorite entity through that code:

/**
* @ORM\OneToMany(targetEntity="Minn\AdsBundle\Entity\MotorsFavorite",
*                mappedBy="motors",cascade={"persist", "remove"})
* @ORM\JoinColumn(nullable=true)
*/
private $favorites;

2.Defining the MotorsFavorite entity as fellows:

<?php

namespace Minn\AdsBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * MotorsFavorite
 *
 * @ORM\Table(
 * uniqueConstraints={@ORM\UniqueConstraint(name="unique_fav_motors",
 *  columns={"user_id", "motors_id"})})
 * @ORM\Entity(repositoryClass="Minn\AdsBundle\Entity\MotorsFavoriteRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class MotorsFavorite {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Minn\UserBundle\Entity\User")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    /**
     * @ORM\ManyToOne(targetEntity="Minn\AdsBundle\Entity\MotorsAds", inversedBy="favorites")
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     */
    private $motors;
//...
}

As you can see, the linkage between the MotorAds and MotorFavorite is a hard linkage, which means that I have to create a Favorite entity for each Ads entity I create (FavoriteMotors, FavoriteRealestate, FavoriteElectronics, ...). This is a long and repetitive work.


So my question is:

1.Creating a super mapped class called SuperMappedFavorite which will only include the $id and $user attributes will reduce the repetitive work. But what about the the attribute $motors? $motors is hardly linked to the entity MotorsAds as you see here:@ORM\ManyToOne(targetEntity="Minn\AdsBundle\Entity\MotorsAds", inversedBy="favorites"). All the burden of the work is in the setters and getters of $motors.

2.Is it possible to make the target entity an interface like this:

<?php
// SuperMappedFavorite.php
// ...
@ORM\ManyToOne(targetEntity="Minn\AdsBundle\Favorite\FavoriteAwareInterface", inversedBy="favorites")
private $object;
// ...

and the MotorsAds entity will be implementing in this the FavoriteAwareInterface

If anyone has a good link/article regarding this kind of issue, I will be happy to have it.

Thanks.

1 Answer 1

1

Yes, you can set an interface as target entity, as described in the Symfony documentation.

The process is basically:

  • defining the interface (your Minn\AdsBundle\Favorite\FavoriteAwareInterface),
  • setting the interface in the parent entity (as you already did),
  • implementing the interface in a different entity (would be class MotorsFavorite implements FavoriteAwareInterface) – and yes, it can also be derived from a mapped superclass,
  • and then telling Doctrine to use your implementation through the doctrine.orm.resolve_target_entities config parameter.

See the documentation for details and a code example.

Sign up to request clarification or add additional context in comments.

3 Comments

you are great @lxg doctrine.orm.resolve_target_entities is the keywork I am looking for ;)
@aminejallouli: I have seen that you had made an edit which was rejected by the mods (apparently because it is a new question attached to a given answer). Can you please simply post a new SO question scoped to the new problem, maybe with a link to this one.
It seems that replacing an interface by a real object can be done only once. This is not my case since I need to do this multiple time for each Ads entity. You can see this link github.com/doctrine/DoctrineBundle/issues/328

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.