Search code examples
databasesymfonydoctrinemappingentity-relationship

Symfony2 + Doctrine Object/Database mapping


I am creating a CMS where all pages for our website can be added/updated/deleted/re-positioned etc. I am creating a oneToMany relationship between pages and page_versions so each time a page is amended in the CMS a copy will be saved as a page_version so we can revert back to this version if needed. Also, when someone is currently editing a page, it will become locked so no other user can edit it at the same time. Each page can also have a parent page and each page can have multiple rewrite rules using another oneToMany relationship with the rewrite_rules table. However, there are a few fields which I am unsure as to what table they should be in and how they can be used as objects when mapping using Symfony2 and Doctrine entity relationships. Here are my tables at the moment:

page table

id
parent_id
locked

page_version table
page_id
title
content
enabled
position

rewrite_rules table
id
page_id
rewrite
canonical

My questions are:

  1. Should the position field be within the page table or page_version table? The position for each page will not change depending on the version of the page. This will only be changed in the list view of all pages. This is so that if you have for example,5 child pages of the 'About Us' page, these can be ordered for rendering the output on the front end.
  2. Should the rewrite_rules table join the page table or page_version table? Again, this will be linked to a page rather than the version. If someone edits a version of a page and adds a rewrite rule, this will be applied to the page, not just that version of the page. I.e if you were to revert back to an older version, the rewrite rule would still apply to this version.
  3. To make a page version the active page, should this be a simple field in the page table or in the page_version table?

    Thanks

    UPDATE

Here are my Page and PageVersion classes:

class Page
{
    /**
    * @ORM\OneToMany(targetEntity="PageVersion", mappedBy="page")
    */
   private $pageversions;
}
class PageVersion
{
    /**
     * @var page
     *
     * @ORM\ManyToOne(targetEntity="Page", inversedBy="pageversions")
     *
     */
    private $page;

}

Solution

  • Consider that versioning associations becomes really annoying on the long term. Also, you should probably remove OneToMany relations and keep only the ManyToOne side of them.

    This makes it easier to version your data by using a tool like EntityAudit, which unfortunately didn't work in my case (doesn't support inheritances).

    So my advice is:

    1. if it's not relevant to version a property, then don't do it. Versioning is a complex problem, and an expensive one too. YAGNI.
    2. if you want to track if a page had rewrite rules or not in the past, you will need to version the association, but since the rewrite rule doesn't have effects per-version, YAGNI. In my opinion you may just connect a page with a rewrite (also here: keep the association uni-directional if possible).
    3. You will probably need a reference to the "active" page in the "page" object. This speeds up queries quite a bit, plus makes it easier for you to work with the OOP API.