Content structure for a CMS
I'm working on a modular CMS and I was thinking about the content architecture a lot. I needed a flexible system which will allow for easy creation of different content types. Eve开发者_高级运维ry content type has a module (or a method in some other module) which handles it. That module handles creation, manipulation and helps at displaying content (Views are responsible for viewing content and modules give them the informations).
Every content type has it's own table and is unaware of other content types.
The Contents and Content_types are the tables that are responsible for storing the information about contents.
Contents
---------------------------------------------------------------------------------------
id slug content_type_id in_table_id language_id uid parent_id
1 about-us 1 1 1 83j8je29 0
2 o-nama 1 2 2 83j8je29 0
3 first-page 1 3 1 12j83j28 0
4 prva-strana 1 4 2 12j83j28 0
5 news 2 1 1 mSk2919k 0
6 vijesti 2 2 2 mSk2919k 0
7 breaking-title 3 1 1 B8392mkA 5
8 vazna-vijest 3 2 2 B8392mkA 6
Content_types
------------------
id content_type
1 page
2 category
3 article
The Contents table holds the slug for the content, the content type, the ID of the content in the table of that type of content, language ID, uid - which is unique to the content, so we can easily pair multilingual content, and a parent ID.
This is languages table...
Languages
---------------------------
id friendly_name sid
1 english eng
2 hrvatski cro
And this is an example of a content type table.
Pages
---------------------------------------------------------------
id title content author_id
1 About Us This is a page about us blah blah 5
2 O nama Ovo je stranica o nama 5
3 First Page Content 2
4 Prva strana Sadržaj 3
So, how all this functions?
Let's say we go to: http://www.website.org/en/about-us
- Determine the language (en) and find out it's ID (which is 1)
- Determine the slug (about-us)
- Select the content with the language ID of 1 and slug "about-us"
- Determine the content type and the in_table_id
- Call the module responsible for opening(handling) that type of content
- Module is now loaded. It now finds the page with the ID of 1 and displays it.
Another example: http://www.website.org/en/news/breaking-title
- Determine the language (en) and find out it's ID (which is 1)
- Determine the slug (news)
- We have two slugs (breaking-title)
- Now we find content with "breaking-title" slug which parent is "news"
- Call the module responsible for opening(handling) that type of content
- Module is now loaded. It now finds the article with the ID of 1 and displays it.
If we would go to the http://www.website.org/en/news/ it would determine it's a category and call a module responsible for handling categories and do what we need (which in this case is display all of the children content)
I think I came up with a really flexible system, but as I am not really experienced programmer (I'm 17 years old) I'm not really sure about it so I ask you what do you think about this concept?
I've recently became a fan of storing these types of data as metadata. The clear benefit is that you can have a single table for all your content types, and (having a 5NF normalized db structure) a maximum of two additional tables for storing metadata references and metadata actual values. This allows a high level of data abstraction and a general model for persistency. And all these hype words translate to faster development.
To give you an example, Elgg, a popular php-based social networking framework, does a good job at this kind of storage. Flow3, a conceptual but very neat, general purpose php development framework, also uses metadata for persistency.
The greatest benefit of the metadata approach is that you can forget about SQL statements in your code, once and for all. Given you have the right persistence abstraction, you can create persistent objects like:
$car = new StdClass();
$car->type = 'car';
$car->fuel_required = 'petrol';
$car->engine_cc = 2400;
$car->max_passengers = 5;
$car-save();
And your persistency framework would take care about the save() function itself, by iterating over object properties, and saving them in the metadata tables. If you need a working example of all this, I'd again suggest installing and trying Elgg. You'll see that practically any kind of new content will be inserted into the same 3-4 tables.
There is some controversy around using the metadata approach, mostly performance based. It is undeniable that using this approach, your meta tables will fill up very quickly. However, assuming your indexes are in place, your queries will give you reasonable response times, even when there are tens of millions of records in the meta tables. And, best of all, if you're not happy to scale your infrastructure as your business grows, you can turn to "Amazon s3" or other distributed data storage solution to handle your scalability needs.
精彩评论