链接1实体与许多其他类型的实体

时间:2014-03-04 08:39:56

标签: symfony

假设我有一个公司,我管理Employees, Cars, Contracts, Buildings, Sites, Products,等等。您可以猜测,这些是非常独立的事情,因此不可能有继承

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

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

  1. 在Document和Employee之间创建ManyToMany关系,在Document和Car之间创建另一个关系。
    • 问题:我必须复制Controller代码以附加文档,复制表单等。
  2. 创建一个包含文档ID,相关实体ID和相关实体类名的联接表。
    • 问题:它对我来说看起来并不干净,我没有真正以这种方式挖掘,但我觉得我会有很多&#34 ;实体映射"问题。
  3. 有什么建议吗?


    [编辑]

    事实上,我必须对Document执行相同的操作:我需要将一些Event与某些Events和/或某些Employees等相关联。在我的实际情况中,我有超过10个实体与Cars和/或Event相关联,这意味着如果我使用解决方案1,则会复制20倍以上的代码!

2 个答案:

答案 0 :(得分:1)

假设您正在使用Doctrine ORM,我认为您正在搜索Mapped Superclasses继承。

文档比文字更好:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#mapped-superclasses

答案 1 :(得分:0)

所以最后我设法解决了我的问题,遵循@ Rpg600关于Mapped Superclasses的想法。

这可能不是有史以来最好,最干净的解决方案,我并不为此感到骄傲,但它确实起到了作用,它仍然比我的第一个想法更好。

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

/**
 * 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 ...

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之间的链接:

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

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文件中我导入了常见的“文档列表”显示。

那是所有人!

我希望这有助于:)