Application Lego: Build a Wiki with Symfony in 20 Minutes
This tutorial shows how fast you can develop with symfony. It showcases symfony's admin generator capabilities, and makes great use of a couple of symfony plugins.
Installation
Start with an empty symfony sandbox. Then use the symfony command line to install two plugins from the symfony plugins repository. Open a terminal, go to the sf_sandbox repository and type:
> php symfony plugin-install http://plugins.symfony-project.com/sfPropelVersionableBehaviorPlugin
> php symfony plugin-install http://plugins.symfony-project.com/sfAdvancedAdminGeneratorPlugin
The first plugin requires one change in the default symfony configuration, since it is a behavior. A behavior is a model modification bringing additional capabilities to the model classes for which it is enabled. To activate behaviors in your symfony project, you need to change the last line of the config/propel.ini to:
propel.builder.addBehaviors = true
Model initialization
A wiki is basically a tool to manage articles and to keep every modification of these articles. This means that you need at least an article table to store the information of the articles. So define the following structure in the config/schema.yml file:
propel:
article:
id: ~
title: varchar(255)
body: longvarchar
version: integer
updated_at: ~
From this description, symfony can both initialize a database and an object model to map the table to an object-oriented API. You just need to type in the command line:
> php symfony propel-build-all
The Article model should be versionable, so that every modification to it creates a new version. Thanks to the plugin you just installed, this is as easy as adding this line at the end of the lib/model/Article.php model file:
sfPropelBehavior::add('Article', array('versionable'));
One last thing: clear the cache. Don't forget to do this every time you add a class
> php symfony clear-cache
Check that nothing is broken by browsing to the application's default page:
http://localhost/sf_sandbox/web/frontend_dev.php
Article edition interface
Use the command line to create a wiki module based on the Article model with the admin generator:
> php symfony propel-init-admin frontend wiki Article
Play with the apps/frontend/modules/wiki/config/generator.yml file until you get something satisfactory, or paste the following configuration:
generator:
class: sfAdvancedAdminGenerator
param:
model_class: Article
theme: default
list:
title: List of Articles
sort: title
click_action: show
display: [=title, updated_at]
filters: [title, updated_at]
object_actions:
_show: { name: View Article }
_edit: { name: Edit Article }
show:
actions:
_list: { name: Back to the list }
_edit: { name: Edit Article }
edit:
fields:
updated_at: { type: plain }
version: { type: plain }
body: { params: size=80x15 }
actions:
_save: { name: Save modifications }
_show: { name: View Article }
_list: { name: Back to the list }
_delete: { name: Delete Article }
The results should be visible at the following URL. Go on, play with the interface, enter a few articles, try to edit one a few times - you will see that the version number automatically increases in the show view. That's one of the benefits offered by the sfPropelVersionableBehaviorPlugin.
http://localhost/sf_sandbox/web/frontend_dev.php/wiki
Note that the above file uses an extension for the symfony Admin Generator called sfAdvancedAdminGenerator - that's the purpose of the second plugin you installed. It offers a "show" view and separates the "create" view from the "edit" one. Apart from that, the syntax is a simple illustration of the Admin Generator capabilities - refer to the 'Admin Generator' Chapter in the symfony book for more information.
History of modifications on an article
A wiki keeps every revision of an article, and offers a list of past revisions. So you will add a history action to the wiki module. Edit the apps/frontend/modules/wiki/actions/actions.class.php class and add the following method:
{
$this->article = $this->getArticleOrCreate();
}
This method just reuses an existing method created by the Admin Generator. This getArticleOrCreate returns an Article object based on the id request parameter. If you are curious about how this method works, you will find the generated actions class in cache/frontend/dev/modules/autoWiki/actions/actions.class.php.
Now, to the history template. Create a apps/frontend/modules/wiki/templates/historySuccess.php file with the following content:
<div id="sf_admin_container">
<h1><?php echo sprintf('History of "%s" modifications', $article->getTitle()) ?></h1>
<div id="sf_admin_content">
<?php foreach ($article->getAllResourceVersions('desc') as $resourceVersion): ?>
<div class="form-row">
<?php echo sprintf("'%s', Version %d, updated on %s (%s)\n",
link_to($resourceVersion->getTitle(), 'wiki/show?id='.$article->getId().'&version='.$resourceVersion->getNumber()),
$resourceVersion->getNumber(),
$resourceVersion->getCreatedAt(),
$resourceVersion->getComment()
) ?>
</div>
<?php endforeach; ?>
<ul class="sf_admin_actions">
<li><?php echo button_to('Show Article', 'wiki/show?id='.$article->getId(), 'class=sf_admin_action_show') ?></li>
<li><?php echo button_to('Edit Article', 'wiki/edit?id='.$article->getId(), 'class=sf_admin_action_edit') ?></li>
</ul>
</div>
</div>
The getAllResourceVersions() method is a model extension provided by the sfPropelVersionableBehaviorPlugin, which returns an array of ResourceVersion objects, each giving details about a particular revision.
To check the resulting HTML for the new action and template, just browse to:
http://localhost/sf_sandbox/web/frontend_dev.php/wiki/history/id/1
You should see the history of modifications of the article of id 1. Each revisions provides a link to the show view. For this link to display the correct version, you need to override one method of the actions class. Basically, if a version parameter is present in the request, this method forces the article to this version.
{
$article = parent::getArticleOrCreate($id);
if($this->getRequest()->hasParameter('version'))
{
$article->toVersion($this->getRequest()->getParameter('version'));
}
return $article;
}
That's about all. Oh, yes, you can plug the history page into your other generator's pages by modifying the generator.yml. For both the show and the edit view, add the following entry under the actions: key:
_history: { name: History }
Conclusion
In about 50 lines and 20 minutes, you have a working wiki, with search, sorting and pagination capabilities. You can review (and reuse) any older revision of an article. Of course, this is not enough to publish your new app as a shiny open-source project - you should at least add user authentication through sfGuardPlugin and article formatting through markdown. Maybe you will need to write an additional 20 lines of code for that.
But that illustrates how to build up an application with symfony. The framework and the plugins provide the features, you just assemble them and glue them together according to your needs. Just like you used to assemble Legos to create a fire station. Since there are very few lines of code, the application is easy to review, maintain, and run.

Nice tutorial François. Thanks a lot
Excellent. I’ve been meaning to install the sfPropelVersionableBehaviorPlugin on one of my production sites. I’ll go through this tutorial first and give it a test drive.
Built the wiki in less than 20 minutes using Symfony 1.0 and mysql. Any hints on getting the wiki working with Symfony 1.1? For example, what is the URL to download sfPropelVersionableBehaviorPlugin for Symfony 1.1?
me ha encantado el tutorial
Oh, That’s fine. Thank you for this practical tutorial.
Good to see another tutorial based around something a little different.