Dynamic pages
We will store the pages in a database table. Right? So what information is needed a page? We will use a WYSIWYG JavaScript editor which handles an HTML page as a big text field. Therefore the
content will be stored in one single big MEDIUMTEXT field because the 65K limit by normal TEXT is surprisingly low. We will also need a page id. Moreover we should have a title for the page to be able to spot it in the yet-to-come administration system. For the future we will, however include an idx field that we use for ordering the pages in administration and sitemap listing. We will also have a description field that we use for user sitemaps. And to please the search engines we have a last_modified field as well. Hmm.... let's add a visible field to be able to hide a page from sitemaps and search engines.
If you have not yet created a database, please do it now and have a look at our notes as well.
After doing this should log in as the correct user and select the database you have just created and create the table for the upcoming pages:
CREATE TABLE cms_pages (
id int(11) NOT NULL auto_increment,
idx int(11) NOT NULL,
link_name varchar(255) NOT NULL default '', /* internal */
visible tinyint(4) NOT NULL default '1', /* SEO */
last_modified timestamp NOT NULL default CURRENT_TIMESTAMP,
title varchar(255) default NULL,
description varchar(255) NOT NULL
content mediumtext,
container_class varchar(255) NOT NULL default '',
PRIMARY KEY (id),
KEY visible (visible),
KEY idx (idx),
KEY link_name (link_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
That is a pretty minimalist approach.
Storing images
You can but you should never store images or other binary data in the database. Never. You may think you might benefit from it (looking at the solution from an administrative point of view) but they will result in more problems than plus sides. The most important fact is that serving something from the database uses considerably more CPU and I/O resources than serving it from the file system.
Therefore, we will reserve a few file system slots for files we will be using in our database-stored pages. We will very probably be using images, possibly sounds and maybe some Acrobat Reader files as well. Let’s add this structure to our directory path:
/[web application root]
|
+-/files| || +-/image| || +-/sound| || +-/pdf|
...
So if we have an image in our page it will be referred to as follows:
<img alt="balloon" src="/files/image/balloon.jpg" />
Please note: We are using "friendly urls" and therefore the image path must start with a forward slash. Why? If you have a page address like "http://skoopcms.com/front_page" and on the page you have link "files/image/balloon.jpg" every browser will try to append the image path to the existing path. Instead, if you start the image path with a forward slash the browser will search for the image starting from the domain root directory.
We will start with a very simple solution that will not allow us to work in a visual layout editor from the very start but – believe us – we will be there sooner or later!
Okay. Now it is time to create a couple of real pages. Below you will find a couple of SQL insert statements to do the job:
insert into cms_pages(idx,link_name,content) values(1,"front_page","<h1>Front Page</h1><p>Welcome to our site</p>");
insert into cms_pages(idx,link_name,content) values(2,"image_page","<h1>Image page</h1><p>Image below</p><img src=’/files/image/balloon.jpg’ alt=’’ />");
You can, of course, do this in PhpMyAdmin, HeidiSQL or any tool you wish. If you are using references to local images, please remember to save them to the appropriate folder. Notice that we are using the MySQL automatic time stamping feature and when updating the last_modified value we only need to set it NULL.
The Dynamic Page module
What we need next is a module that loads and shows the page. The module should
- get the page name using some mechanism
- fetch the content from the database.
- return the content to the caller
We will use the first piece in the URL following our server name. If the URL is
http://www.oursite.com/front_page
we will try to load the content with link_name = "front_page". If you have a look at our main template you can see that the string "front_page" will not match any of the alternatives in the chain so it will fire the "else" part.
Bearing all this in mind we will write our first real and the most important module.
dynamic_page_module.php
... wait a moment...
As you can see there is not much here. The rudimentary error reporting should be a bit more elaborate, of course. We could manage without a special template because the module will return clean HTML from the database. We could just as well have a single line:
return $content;
directly after we have got the correct content from the database. We have, however, added something for the future and use a very, very simple template to output the contents. Why? Sometimes it is nice to have the option to use a dedicated class for some special page and give both the page name and the class name in the template statement:
{cmsmodule name="dynamic_page" page="xssredir" path="modules/pages" pageclass="xss"}
This might be handy if we detect an XSS attack, for instance and want to redirect the attacker to a warning page. That very line already exists in the main template of this site so go ahead and try it :) The page template looks like this:
dynamic_page.tpl
... wait a moment...
Save the above to your modules directory as follows:
+-/modules
| |
| +-/pages
| |
| +-dynamic_page_module.php
| |
| +-/templates
| |
| +-/dynamic_page.tpl
The logic for this module should already be included in the main template. The rule in the template is: If all else fails try to load a page with the same name as the command.
Once again, this is only one of the many ways of doing this. We chose it because it is self-explanatory.
But what is that 'handlespecial...' stuff?
Oh, we are looking into the bright future here. Because our WYSIWYG editor is not omnipotent we reserve the possibility to create special tags. The pages you are reading now are already using that functionality. The expandable code sections have been written using a special tag handler, for instance. The idea is that we can create a special tag which we grab and mutilate in our handler and produce something that cannot be done using the basic tools.
The highlighted code segments in this site have been declared approximately as follows (tag name changed from "code" to "hlcode" for a very good reason):
{hlcode|php|file|files/code/example.php}
This line tells the tag handler that we have php code in the file system in file files/code/example.php. A special template is used to create the highlighted code. You will see how we have done this, rest assured.