CMS database schema - php

I'm building a custom CMS system usign PHP and MySQL. My CMS will have pages. Each page is of a type. Each page type has assigned some properties of different types (number, text, etc.). I'm currently creating the database for storing these things - page types, properties, pages and property values. The first solution is to have 4 different tables:
=pages=
page_id
page_type_id
page_name
=page_types=
page_type_id
page_type_name
=page_properties=
property_id
property_name
=page_property_values=
page_id
property_id
property_value
The only problem is, that I would have to save all kind of properties to the same data type filed (for example varchar). What I really want is to save boolean data to boolean field.
My second solution is to create a separate table for each page type. For example:
=page_type_text_page=
page_id
title [varchar]
content [text]
active [boolean]
Could somebody help me, how to modify this structure in order to get the right solution?

A third option might be something in the lines of
property_types
property_type_id
property_name
property_datatype
page_property_values
page_id
property_id
property_stringvalue
property_boolvalue
property_intvalue
property_datetimevalue
...
..where you'd use just one of the value columns for a certain page property and leave the rest empty. This way you would be able to get all the properties for a page in a single call with a couple of joins and then programatically fetch the value from the apropriate column by looking at the property data type.

I would like to help you with some of my experiences:
Do not build your own CMS - it may not be a good idea. It is very complicated to do it right. Use/modify some open-source CMS (Wordpress, Joomla, etc) to get what you want.
If I would be creating a new CMS do not use PHP and MySQL combination, because it's already done, and it's done pretty good with great community. Maybe you can try something thats not done yet - Node.js CMS, Single page application CMS and use some mongoDB etc.
If you really want build your own CMS based on PHP MySQL and don't know right database structure, inspire yourself with open-source CMS, like I said Wordpress, Joomla, Drupal etc. Its more complicated than what you describe, but you can use only what you want.

Related

Concrete5: User Attributes vs Custom DB-Table, what are the Pros and Cons?

I'm developing a page with C5 needing various data to be attached to the user accounts. There are two types of users, having different data. Some of the data is multi dimensional and therefor needs custom DB tables. My question is now if it makes sense to store all data in custom DB tables or to use user attributes for the one dimensional data.
Probably there is no general answer to this, but maybe some pros and cons?
I'm often asking myself where to store data in Concrete5 and would be interested how others decide ...
Yeah. I'd definitely store as user attributes for similar reasons to the one you've already identified (visible, searchable, etc).
concrete5 is extensible, but not super extensible; you can attach data to a user using attributes, but not through some totally custom object / db table that you also expect to, e.g., show up on the user profile page.
Oftentimes in c5 (like any other framework), doing it the Right way (attribute) is more difficult (especially for the first "object", but also for each additional one) than just creating a db table and linking to a user id. But, like in all frameworks, you'll reap benefits down the road that you hadn't even considered. This is in searching, upgradability, and things that might only occur to the guy who takes over development next year.
So, with all that being said, go with attributes. And not just for the one dimensional data. You can configure the attribute controller (and the db schema behind it) to store any data you wish. Look at the Address attribute. This contains multiple fields (though it's still 1D). I think there's an opensource "multi address" attribute out there which stores 1-n addresses as a single attribute. You can do this with an additional linked table, but I've recently gotten lazy with c5 and done no-mysql by dumping json_encode()ed (multi-dimensional) arrays in the "data" field. (In this case, your attribute doesn't even need its own table -- it can use the Default table.) You can then configure the editing interface and also the display value (so, e.g., it just shows a list of each sub-object's Name property). Similarly, you can configure the text that gets indexed for searching purposes.
You asked for pros/cons. Doing this custom will be quicker and more straightforward. Extending an attribute, especially to create something complex, isn't super simple, and there isn't a lot of good documentation. Also, the attribute-editing UI (on the user dashboard page) is a bit kludgy. Yes, you get to "design" whatever you want within the "table cell", but you're still limited to making the admin click on the attribute name, using your editing interface within the cell, and then (ideally) clicking on the little disk icon. (Creating a javascript dialog might solve some issues here.)

How to query for multiple types of an object (using a key-value table) and grouping the results together as a complete object

I hope I asked the question properly. I have a table of objects grouped by object_id. They are stored as a key / value. I thought this would be simple but I cannot find a solution anywhere. I'm trying to get the most efficient method of querying against this table to return a full object based on multiple meta_name values. Here's the table structure:
Here's the code I have so far, which works great to query one value:
SELECT data2.object_id,data2.object, data2.meta_name, data2.value_string, data2.value_text FROM meta_data AS data1
LEFT JOIN meta_data AS data2 ON(data1.object_id = data2.object_id)
data1.object="domain"
AND data1.meta_name = "category"
AND data1.value_string = "programmer"
This gives me the following results. This is great for a single taxonomy (domain in category programmer).
The problem comes when I want to query for all domains with category programmer AND color red AND possibly other meta_name = value_strings. I can find no solution for this outside of making multiple queries from PHP (which I want to avoid for obvious performance reasons).
I need to point out that objects will be created on the fly, and without a specific schema (which is the point of having this structure to begin with) so I cannot hard code and assume anything about an object (Objects may have more meta properties defined to them from the admin panel at any given time).
Again, I hope I am asking this question right, since I have been completely unlucky in finding a solution by searching online for the last 3 days.
Thank you so much ahead of time to the MySQL pro that can help me with this!
In situations like this solutions typically query all records to avoid multiple queries and then stitch data objects together to provide the desired format. Then you can develop simple find() methods on those objects to further filter the results (e.g. using array functions)
If you're interested in exact implementation, I encourage you to look at WordPress - you noted taxonomies. As an open source project you can review their code for an example of how this is done. Take a look at the Taxonomies API as well as Meta API.

Sitewide multi object search - database design / code strategy?

I am lost on how to best approach the site search component. I have a user content site similar to yelp. People can search for local places, local events, local photos, members, etc. So if i enter "Tom" in the search box I expect the search to return results from all user objects that match with Tom. Now the word Tom can be anywhere, like a restaurant name or in the description of the restaurant or in the review, or in someone's comment, etc.
So if i design this purely using normalized sql I will need to join about 15 object tables to scan all the different user objects + scan multiple colunms in each table to search all the fields/colunms. Now I dont know if this is how it is done normally or is there a better way? I have seen stuff like Solr/Apache/Elasticsearch but I am not sure how these fit in to myusecase and even if i use these I assume i still need to scan all the 15 tables + 30-40 colunms correct? My platform is php/mysql. Also any coding / component architecture / DB design practice to follow for this? A friend said i should combine all objects into 1 table but that wont work as you cant combine photos, videos, comments, pages, profiles, etc into 1 table so I am lost on how to implement this.
Probably your friend meant combining all the searchable fields into one table.
The basic idea would be to create a table that acts as the index. One column is indexable and stores words, whereas the other column contains a list of references to objects that contain that word in one of those fields (for example, an object may be a picture, and its searchable fields might be title and comments).
The list of references can be stored in many ways, so you could for example have string of variable length, say a BLOB, and in it store a JSON-encoded array of the ids & types of objects, so that you could easily find them afterwards by doing a search for that id in the table corresponding to the type of object).
Of course, on any addition / removal / modification of indexable data, you should update your index accordingly (but you can use lazy update techniques that eventually update the index in the background - that is because most people expect indexes to be accurate within maybe a few minutes to the current state of the data. One implementation of such an index is Apache Cassandra, but I wouldn't use it for small-scale projects, where you don't need distributed databases and such).

display several tables in pagination

I am using cake php and mysql.
I have several tables that all link up to a table called relates. The relates table holds the primary ids for all the other tables. example I have a table called clients its primary key is called id in the relates table its called client_id.
heres my deal i created a crud application in cakephp it works great, but it only displays information via pagination for one table. I would like to use pagination to display several tables at once so i can display my clients table and another tables like clientsphone table ect. I tried a few things out but i am completely lost. In my relates table i created pagination for it and it shows the primary ids when you click the primary id is goes to the proper record and displays the information from that table, but display just numbers wont help anyone if you dont know what it is.
how can i display several tables at once for the relates table ? any advice would be great
This really depends on what you're looking for.
If you'd like to have all the data at hand but not necessarily on screen at once, a great solution would be to use jQuery's UI Tabs. You could throw each table in a separate div and easily toggle them with the tabs.
You could display multiple at once a la a stock trading application. But from a UI standpoint that can get ugly in a hurry.
How about dynamically building one gigantic table via HTML or JSON string then using jQuery's datatables to paginate, sort, filter, and show/hide columns? That probably would give you the best of all worlds while still making it readable to your users. You could also use Datatables and tabs together to get more than one at a time. Datatables is the easiest way I can think of to make a standard table more user friendly quickly.

PHP/MySQL database design for various/variable content - modular system

I'm trying to build (right now just thinking/planning/drawing relations :] ) little modular system to build basic websites (mostly to simplify common tasks we as webdesigners do routinely).
I got little stuck with database design / whole idea of storing content.
1., What is mostly painful on most of websites (from my experience), are pages with quasi same layout/skelet, with different information - e.g. Title, picture, and set of information - but, making special templates / special modules in cms happens to cost more energy than edit it as a text - however, here we lose some operational potential - we can't get "only titles", because, CMS/system understands whole content as one textfield
So, I would like to this two tables - one to hold information what structure the content has (e.g. just variable amount of photos <1;500) :], title & text & photo (large) & gallery) - HOW - and another table with all contents, modules and parts of "collections" (my working name for various structured information) - WHAT
table module_descriptors (HOW)
id int
structure - *???*
table modules (WHAT)
id int
module_type - #link to module_descriptors id
content - *???*
2., What I like about this is - I don't need many tables - I don't like databases with 6810 tables, one for each module, for it's description, for misc. number to text relations, ... and I also don't like tables with 60 columns, like content_us, content_it, category_id, parent_id.
I'm thinking I could hold the structure description and content itself (noted the ??? ?) as either XML or CSV, but maybe I'm trying to reinvent the wheel and answer to this is hidden in some design pattern I haven't looked into.
Hope I make any sense at all and would get some replies - give me your opinion, pros, cons... or send me to hell. Thank you
EDIT: My question is also this: Does this approach make sense? Is it edit-friendly? Isn't there something better? Is it moral? Don't do kittens die when I do this? Isn't it too much for server, If I want to read&compare 30 XMLs pulled from DB (e.g. I want to compare something)? The technical part - how to do it - is just one part of question:)
The design pattern you're hinting at is called Serialized LOB. You can store some data in the conventional way (as columns) for attributes that are the same for every entry. For attributes that are variable, format them as XML or MarkDown or whatever you want, and store it in a TEXT BLOB.
Of course you lose the ability to use SQL expressions to query individual elements within the BLOB. Anything you need to use in searching or sorting should be in conventional columns.
Re comment: If your text blob is in XML format, you could search it with XML functions supported by MySQL 5.1 and later. But this cannot benefit from an index, so it's going to result in very slow searches.
The same is true if you try to use LIKE or RLIKE with wildcards. Without using an index, searches will result in full table-scans.
You could also try to use a MySQL FULLTEXT index, but this isn't a good solution for searching XML data, because it won't be able to tell the difference between text content and XML tag names and XML attributes.
So just use conventional columns for any fields you want to search or sort by. You'll be happier that way.
Re question: If your documents really require variable structure, you have few choices. When used properly, SQL assumes that every row has the same structure (that is, columns). Your alternatives are:
Single Table Inheritance or Concrete Table Inheritance or Class Table Inheritance
Serialized LOB
Non-relational databases
Some people resort to an antipattern called Entity-Attribute-Value (EAV) to store variable attributes, but honestly, don't go there. For a story about how bad this can go wrong, read this article: Bad CaRMa.

Categories