2016-04-05 54 views
2

在我的應用程序中,我有幾個實體共享一些共同的屬性。例如實體:主義繼承性能

  • 圖片
  • 視頻
  • 事件
  • ForumPost

我想這些類都有一些共同的功能,如:

  • 有一個列表的評論,以及保留評論
  • 投票
  • 用戶和用戶列表統計
  • 查看次數
  • 等。

我真的不想重複這些功能對於上述每個實體。所以......我一直在閱讀關於Doctrine繼承映射的知識,並且我提出了一個想法,即「Class Table Inheritance」是解決這個問題最優雅的方法。該計劃如下:

  1. 創建一個父帖子實體

    /** 
    * @ORM\Entity 
    * @ORM\InheritanceType("JOINED") 
    * @ORM\DiscriminatorColumn(name="type", type="string") 
    */ 
    class Post 
    { 
        protected $likeCount; 
    
        protected $subscriberCount; 
    
        protected $subscribers; 
    
        // ... 
    } 
    
  2. 有很多一對一的喜歡,評論,投票等關係到發佈實體:

    class PostLike 
    { 
        /** 
        * @ORM\ManyToOne(targetEntity="Post") 
        * @ORM\JoinColumn(name="post_id", referencedColumnName="id", nullable=false) 
        */ 
        protected $post; 
    } 
    
  3. 讓圖像,視頻等實體擴展發佈:

    class Video extends Post 
    { 
        // Post properties become available here 
    } 
    

所有的工作都像魅力直到我看着實際的查詢主義正在執行。問題是:每當我選擇一個PostLike時,doctrine也會急切地加載Post實體,這也將加入所有的子表。因此,例如,一個簡單的PostLike刪除操作會觸發4個表上的聯接,並隨着我的層次結構的增長實際上會加入更多的表。

如果我有10個實體擴展後,這將在10個表上加入。我不是過早優化的粉絲,但這聽起來不像是一個好計劃。

在Doctrine文檔中,實際上在「6.3.2。性能影響」中提到了此行爲。

最後,我的問題:我有什麼其他的選擇來創建可重複使用教條的表?

我正在考慮做一對一的映射(發佈實體是視頻的屬性,以及圖像等),但我已經在一些博客中看過一對一的映射,出於性能方面的原因,還應該避免使用原則。

謝謝!

編輯和ansewer拉斐爾Malié關於所映射超:

我知道我可以使用映射超和特質功能,以避免代碼重複。但是,這些功能允許我重用代碼,但不允許我重用sql表。這裏是一個例子:

說我想圖像,視頻和事件實體有意見。我可以創建一個Mapped Superclass AbstractComment,然後在ImageComment,VideoComment,EventComment中進行擴展。接下來,我想添加評論票。由於我無法重用相同的SQL表,因此我需要創建ImageCommentVote,VideoCommentVote,EventCommentVote等。然後,我希望用戶能夠報告濫用評論。還有一次:ImageCommentReport,VideoCommentReport,EventCommentReport。你明白了。我想添加到評論中的每個功能都需要爲每個實體(如圖像,視頻等)提供單獨的表格。很多表格。

爲什麼我更喜歡使用,而不是使用特點與許多表集中式方法的原因:

  • 便於管理。通過向一個表發送查詢,我可以輕鬆地搜索/編輯/刪除整個應用程序的註釋。
  • 相同的控制器可以處理多個實體的操作,不需要創建一個抽象的和許多具體的控制器
  • 當集中操作時,顯示關於新評論/喜歡等的用戶通知要容易得多。

我也意識到這樣的系統的缺點,但我現在可以和他們一起生活。我的問題是如何在沒有必要的情況下實際上加入所有內容,如何讓教義做我想做的事情。

+0

差不多兩年後,我非常好奇,你們一起解決了什麼問題? – BigJ

回答

1

在我看來你做錯了。您的實體除了一些功能之外沒有任何共同之處,因此沒有理由使用single tableclass table繼承。

你應該用性狀:http://php.net/manual/en/language.oop5.traits.php

它的工作原理與原則。您可以使用註釋定義一個或多個具有某些屬性/方法的特徵,然後將這些特徵導入到實體中。

您還可以使用映射超類:http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#mapped-superclasses,它非常接近您的示例,但具有不同的實體註釋。

+0

特徵和映射超類將迫使我爲每個實體使用不同的評論表(例如)。因此,我將不得不使用VideoComment,ImageComment,EventComment等。然後,如果我想添加評論投票,我將需要使用VideoCommentVote,ImageCommentVote,...這種方式隨着添加到評論中的每個功能都會增加。我想要做的是有一個評論實體,它可以與視頻或圖像或任何其他類相關。喜歡,訂閱等也是如此。 – Karolis

0

經過一番思考,你的決定真的取決於你的數據庫的大小。如果它很大,Class Tabel方法的性能下降可能是不可接受的。但是如果你的表很小,性能命中是次要的,你可以使用類表繼承的所有優點,你在文章中討論過。