Movable Type's dynamic publishing allows you to combine static page generation with dynamic pages on a per-template basis. You can use this to balance the publishing and traffic for your weblog, and it gives you the best of both worlds: you can turn on static page generation for frequently-requested pages like your site index and feeds, and use dynamic pages for your monthly, individual, and other archive pages. This completely eliminates the need to manually rebuild your files; when you update the design of your archive templates, for example, the design of your site will immediately be updated without requiring you to rebuild.
In addition to the requirements for Movable Type itself, the dynamic publishing option has the following requirements:
# Disable fancy indexes, so mtview.php gets a chance... Options -Indexes +SymLinksIfOwnerMatch <IfModule mod_rewrite.c> # The mod_rewrite solution is the preferred way to invoke # dynamic pages, because of its flexibility. # Add mtview.php to the list of DirectoryIndex options, listing it last, # so it is invoked only if the common choices aren't present... <IfModule mod_dir.c> DirectoryIndex index.php index.html index.htm default.htm default.html default.asp /mtview.php </IfModule> RewriteEngine on # don't serve mtview.php if the request is for a real directory # (allows the DirectoryIndex lookup to function) RewriteCond %{REQUEST_FILENAME} !-d # don't serve mtview.php if the request is for a real file # (allows the actual file to be served) RewriteCond %{REQUEST_FILENAME} !-f # anything else is handed to mtview.php for resolution RewriteRule ^(.*)$ /mtview.php [L,QSA] </IfModule> <IfModule !mod_rewrite.c> # if mod_rewrite is unavailable, we forward any missing page # or unresolved directory index requests to mtview # if mtview.php can resolve the request, it returns a 200 # result code which prevents any 4xx error code from going # to the server's access logs. However, an error will be # reported in the error log file. If this is your only choice, # and you want to suppress these messages, adding a "LogLevel crit" # directive within your VirtualHost or root configuration for # Apache will turn them off. ErrorDocument 404 /mtview.php ErrorDocument 403 /mtview.php </IfModule>
(If you already have a .htaccess file, simply append the above lines to it.)
The ``mtview.php'' script referenced above will be created once you do a rebuild of the new ``Dynamic Site Bootstrapper'' index template. If your weblog root is in a subdirectory of your site, adjust the path to the ``mtview.php'' script above to match the actual location of this file (ie: use ``/weblog/mtview.php'' if your weblog root is under a ``weblog'' directory).
Your Apache server should also be configured to use mod_rewrite if it isn't already enabled (you can use the ``httpd -l'' command to list available Apache modules; if the module is dynamically loaded, check your httpd.conf file for a line that begins with ``LoadModule rewrite_module').
Apache should also be configured to utilize .htaccess files. This is also specified in the httpd.conf file for your Apache installation. An example looks like this (depending on your server configuration, this may go in the global context or within a particular VirtualHost section):
<Directory /> AllowOverride All </Directory>
Movable Type has added dynamic publishing as an option in addition to the static publishing it is known for. You don't have to choose just one or the other-- you can have any combination of the two.
This means you can enable dynamic publishing for certain index and/or archive templates and use static publishing for others. This gives you a lot of flexibility in how you publish your site. Depending on your traffic flow, you may want to continue to publish your index and Atom/RSS/RDF feeds statically if those pages receive heavy traffic.
Archive pages are generally the best choice for dynamic publishing since they receive less traffic and consume the most disk space.
Keep in mind that by using dynamic publishing, each un-cached page view will result in a number of database queries to build the page. Depending on the performance of your web server and the complexity of your templates, this may take anywhere from a fraction of a second to several seconds. Here are some tips you can use to optimize the speed of your dynamic pages:
<MTEntries lastn="10">
You may tune this parameter as desired.
Note: This is an experimental feature which may not work in some environments.
Another way to optimize the dynamic publishing feature is to enable page-level caching. This feature gives you near-static page speed, since the dynamic pages are cached into the file system from one request to the next. Over time, this will cause your disk space savings to shrink, but the performance benefit may be worth it.
To enable page-level caching, you will need to create a ``cache'' subdirectory in your weblog's root directory. It should also have a permission mask of 777. After doing this, edit your ``Dynamic Site Bootstrapper'' index template and add this line:
$mt->caching = true;
It should be placed just above the line that reads ``$mt->view();''. Removing this line will disable the caching option.
Once you do that, your dynamic pages will cache themselves into the cache directory you created. Cached pages are individually rebuilt (and only upon request) when the weblog content is newer than the cached page.
If you would like, you can enable conditional requests (HTTP 304 responses) for your dynamic pages. Usually when pages are generated dynamically, they are generated unconditionally. In some cases, this is desired, so conditional requests are disabled by default. You can enable them by adding this to your ``mtview.php'' script:
$mt->conditional = true;
Add this above the ``$mt->view();'' line. The timestamp that is associated with the conditional requests is the last time your weblog was modified (any portion of your weblog, including comments, trackback pings, template changes, etc.).
You can even get fancy and set the conditional behavior conditionally! Here's how you can enable it just for your feeds:
if (preg_match('/(index|atom)\.(rss|xml|rdf)/', $_SERVER['REQUEST_URI'])) { $mt->conditional = true; }
Movable Type's dynamic publishing mode supports plugins as well. The architecture is different, but should be familiar in some respects.
Two key components to the PHP-based dynamic publishing engine are the Smarty template package (http://smarty.php.net/) and Justin Vincent's ezSQL library (http://php.justinvincent.com/).
The ``php'' subdirectory under Movable Type's main directory contains all the files and resources related to the dynamic publishing engine:
mt/php/ lib/ Native MT tags and modules extlib/ Third-party packages (ezSQL and Smarty) plugins/ Third-party MT/PHP plugins
Plugin files should be placed in the ``plugins'' directory. To develop MT/PHP plugins, you should familiarize yourself with how to create add-ons for Smarty. Custom blocks, functions and modifiers are the basis for adding container tags, variable tags and global filters respectively for MT/PHP.
<?php function smarty_function_MTServerUptime($args, &$ctx) { $data = shell_exec('uptime'); return $data; } ?>
Uptime: <$MTServerUptime$>
<?php function smarty_block_MTLoop($args, $content, &$ctx, &$repeat) { if (!isset($content)) { $i = 1; } else { $i = $ctx->stash('i_value') + 1; } if ($i <= 5) { $repeat = true; } else { $repeat = false; } $ctx->stash('i_value', $i); return $content; } ?>
And create ``php/plugins/function.MTLoopIValue.php'':
<?php function smarty_function_MTLoopIValue($args, &$ctx) { return $ctx->stash('i_value'); } ?>
<?php function smarty_block_MTEntryIfTitle($args, $content, &$ctx, &$repeat) { if (!isset($content)) { $e = $ctx->stash('entry'); $title = $e['entry_title']; return $ctx->_hdlr_if($args, $content, $ctx, $repeat, trim($title) != ''); } else { return $ctx->_hdlr_if($args, $content, $ctx, $repeat); } } ?>
Please note that conditional tags should have a ``If'' somewhere in the tag name to function properly with the <MTElse> container tag.
<?php function smarty_modifier_rot13($s, $arg) { // str_rot13 is available in PHP 4.2.0 and later. return str_rot13($s); } ?>
You can then use this filter like this:
<$MTEntryTitle rot13="1"$>
If you require access to the $ctx variable, you can access it through the global ``$mt'' variable, which has a method named context that returns the template context (Smarty object).
An overview of the dynamic publishing architecture is available here: http://www.sixapart.com/pronet/articles/dynamic_publish.html
And for more information on creating custom plugins for MT's PHP layer, refer to this article on our ProNet site: http://www.sixapart.com/pronet/articles/php_dynamic_pub.html
There is also a wealth of information on how to write Smarty routines on the Smarty web site: http://smarty.php.net/manual/en/plugins.php