简体   繁体   中英

Dynamic Target entity Doctrine 2 and Symfony 2

I want dynamic entity mapping on one entity which will be used by other entities. For example, I have a File entity, which will store MIME type, mapping key , name etc, also an entity_id which will contain the id to the entity it belongs to. The mapping key will determine the class as this file entity will be many-to-many. So the targetEntity for File entity isn't fixed. How to achieve that?

File Entity

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * File
 *
 * @ORM\Entity
 */
class File {
    //.... Other mapping properties

    /**
     * @ORM\ManyToOne(targetEntity="SuperClass", inversedBy="files")
     * @ORM\JoinColumn(name="entity_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $entity;
}

Product Entity

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Product
 *
 * @ORM\Entity
 */
class Product extends SuperClass {
    //.... Other mapping properties

    /**
     * @ORM\OneToMany(targetEntity="File", mappedBy="entity")
     */
    protected $files;
}

But I have many other entities similar to Product and how do I make sure that when I call getFiles() , I get the files of the respective entity. I think it may work like this anyway, but is this the right way, or is there a better way?

Ok, this is a very common problem I have - how to link one entity to many others which are very similar.

First, reevaluate: I often find, that I don't actually need that many different entities and that they can be folded into one there by simplifying everything. We often overengineer and overcomplicate when we don't really have to (or even shouldn't)!

If that's not an option: create separate relationships between File and all other (relevant) entities. Yes, your file entity will be full of relationships. Then write one general access getter that computes which entity it is connected to and returning it (either by going through all connections or it can be more involved that that [and faster] by computing it from other params (like mime type in your case). This way you hide the complexity of all those relationsip from the rest of your code.

This option works if you just need a good enough solution. A more correct one would be to forgo doctrine relations and track IDs and related entities classes in two fields and select and instantiate the objects yourself (in the entity, ofcorse). But that's more involved and more error prone.

If you find a way to do this in a more elegant, doctrine2 backed way, please do let me (and the rest of us) know.

I found out that according to my requirements, I can do with ManyToMany Unidirectional or OneToMany Unidirectional. But for bidirectional, there seems to be no solution. I have something in mind, but it will just complicate the Scenario. According to doctrines documentation, the schema Generated will be

CREATE TABLE Product (
    id INT AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE Feature (
    id INT AUTO_INCREMENT NOT NULL,
    product_id INT DEFAULT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;

ALTER TABLE Feature ADD FOREIGN KEY (product_id) REFERENCES Product(id);

So like I suggested in my question to extend a SuperClass, what if the super class to be an entity itself with its own table, containing a field which will store repository path, and somehow it will be processed to return the proper entity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM