将 1 个实体与许多其他类型的实体联系起来 [英] Link 1 entity with many others kind of entities

查看:33
本文介绍了将 1 个实体与许多其他类型的实体联系起来的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一家公司,我负责管理员工、汽车、合同、建筑物、工地、产品等.正如你所猜想的,这些都是非常独立的事情,所以没有继承是可能的.

Let say I have a Company for which I manage Employees, Cars, Contracts, Buildings, Sites, Products, etc. As you can guess, these are quite independant things, so no inheritance is possible.

对于这些元素中的每一个(即实体),我希望能够附加一个或多个Document(点击一个按钮,表单打开,选择一个/several Document 或上传一个新的).

For each of these elements (i.e. Entities), I want to be able to attach one or several Documents (click on a button, form opens, select one/several Document or upload a new one).

Document链接到一种实体不是问题,我的问题是有多种实体.我应该如何管理?我有 2 个想法都有自己的问题...:

Linking Document to one kind of entity is not a problem, my problem is that there are many kinds of entities. How should I manage that? I have 2 ideas which have their own problems...:

  1. 在 Document 和 Employee 之间创建一个 ManyToMany 关系,在 Document 和 Car 之间创建另一个关系,等等.
    • 问题:我必须复制控制器代码以附加文档、复制表单等.
  1. Create a ManyToMany relationship between Document and Employee, another between Document and Car, etc.
    • Problem: I have to duplicate the Controller code to attach Document, duplicate the forms, etc.
  • 问题:对我来说它看起来不太干净,我并没有真正用这种方式挖掘,但我觉得我会有很多实体映射"问题.
  • Problem: it doesn't look really clean to me, I didn't really dig in this way but I feel I'll have a lot of "entity mapping" problems.

有什么建议吗?

事实上我也必须对 Event 做同样的事情:我需要将一些 Events 链接到一些 Employees 和/或链接到一些 Cars 等.在我的真实案例中,我有 10 多个实体要链接到 Event 和/或 Document,这意味着如果我采用解决方案 1,则将代码复制 20 倍以上!

In fact I have to do the same for Event as well: I need to link some Events to some Employees and/or to some Cars, etc. And in my real case, I have more than 10 Entities to be linked to Event and/or Document, which means duplicating more tha 20 times the code if I go with the solution 1!

推荐答案

所以最后我设法解决了我的问题,遵循@Rpg600 关于映射超类的想法.

So finally I managed to solve my problem, following @Rpg600 idea about Mapped Superclasses.

这可能不是有史以来最好和最干净的解决方案,我并不为此感到自豪,但它确实有效,而且仍然比我的第一个想法要好.

This is probably not the best and cleanest solution ever, I'm not really proud of it but it does the job and it is still better than my first ideas.

我创建了一个 BaseEntity,它是我的映射超类(EmployeeCar 等.实体必须扩展这个类):

I create a BaseEntity which is my a mapped superclass (Employee, Car, etc. Entities have to extend this Class):

/**
 * BaseEntity
 * @ORM\MappedSuperclass
 */
class BaseEntity {

    /**
     * @ORM\OneToOne(targetEntity="MyProject\MediaBundle\Entity\Folder")
     */
    private $folder;


    /**
     * Set folder
     * @param \Webobs\MediaBundle\Entity\Folder $folder
     * @return BaseEntity
     */
    public function setFolder(\Webobs\MediaBundle\Entity\Folder $folder = null){
        $this->folder = $folder;        
        return $this;
    }

    /**
     * Get folder
     * @return \Webobs\MediaBundle\Entity\Folder
     */
    public function getFolder(){
        return $this->folder;
    }        
}

由于在超类中不可能有多对多关系,所以我使用了一个 Folder,其中将包含一个或多个 Document.这是解决方案的脏部分;folder 表基本上只包含一个字段,即 id...

As it is not possible to have a Many-to-Many relationship in a superclass, I use a Folder which will contain one or several Document. This is the dirty part of the solution ; the folder table basically contain only one field which is the id...

class Folder
{
    private $id;

    /**
     * Note : Proprietary side
     * @ORM\ManyToMany(targetEntity="MyProject\MediaBundle\Entity\Document", inversedBy="folders", cascade={"persist"})
     * @ORM\JoinTable(name="document_in_folder")
     */
    private $documents;
    // setters and getters

然后我创建一个辅助类(它被声明为服务)来管理任何EntityDocument之间的链接:

Then I create a helper class (which is declared as a service) to manage the link between any Entity and the Document:

class DocumentHelper extends Controller
{
    protected $container;

    /** ************************************************************************
     * Constructor
     * @param type $container
     **************************************************************************/
    public function __construct($container = null)
    {
        $this->container = $container;
    }


    /** ************************************************************************
     * Attach Document(s) to an $entity according to the information given in the
     * form.
     * @param Entity $entity
     * @param string $redirectRouteName Name of the route for the redirection after successfull atachment
     * @param string $redirectParameters Parameters for the redirect route
     * @return Response
     **************************************************************************/
    public function attachToEntity($entity, $redirectRouteName, $redirectParameters)
    {
        $folder = $entity->getFolder();
        if($folder == NULL){
            $folder = new Folder();
            $entity->setFolder($folder);
        }

        $form = $this->createForm(new FolderType(), $folder);

        // ------------- Request Management ------------------------------------
        $request = $this->get('request');
        if ($request->getMethod() == 'POST') {
          $form->bind($request); // Link Request and Form

          if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($folder);
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl($redirectRouteName, $redirectParameters));
          }
        }


        return $this->render('MyProjectMediaBundle:Folder:addDocument.html.twig', array(
            'form'      => $form->createView(),
            'entity'    => $entity,
        ));
    }

这样做,我只需要在每个相关的控制器中添加一个小动作,比如 EmployeeController.php:

Doing that way, I just have to add one small action in each relevant controller, let say EmployeeController.php:

public function addDocumentAction(Employee $employee)
    {        
        $redirectRouteName = 'MyProjectCore_Employee_see';
        $redirectParameters = array('employee_id' => $employee->getId());
        return $this->get('myprojectmedia.documenthelper')->attachToEntity($employee,$redirectRouteName,$redirectParameters);
    }

显示的原理相同,在帮助器中,我在现有的 seeAction() 中调用了通用函数,在 TWIG 文件中,我导入了通用的文档列表"显示.

Same principle for the display, in the helper I have the common function which I call in my already-existing seeAction() and in the TWIG file I import the common "Document list" display.

就是这样!

我希望这可以帮助:)

这篇关于将 1 个实体与许多其他类型的实体联系起来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆