Phase 2: blog
I could have used a package for this, such as WordPress, but as the Symfony documentation uses a blog as an example, I decided to adapt that. In addition to the articles and comments (I'm not intending to use comments at the moment, but might as well include them in the design now), there's also a category for grouping articles. As there was no logic/model to speak of for the static pages, the blog can go in the same app, main. So:
- create new modules blog and category
templates/indexSuccess.php isn't needed for either, so can be deletedsymfony init-module main blog symfony init-module main category - set up config/schema.yml as in documentation, but adding the category table
and the linked id in the article tableblog_category: _attributes: { phpName: Category } id: title: varchar(100) content: varchar(255)category_id: - use sqlite rather than mysql, so edit config/propel.ini appropriately:
(I don't really understand the syntax of the sqlite:// url here, but never mind; this appears to be what works)propel.database = sqlite propel.database.createUrl = sqlite://.//path/to/db propel.database.url = sqlite://.//path/to/db - and edit config/databases.yml to use sqlite rather than mysql:
all: propel: class: sfPropelDatabase param: phptype: sqlite database: %SF_DATA_DIR%/blog.db - create db and generate CRUD in new modules called 'blog' and 'category' (not forgetting to clear the cache and make sure the server can write to the db file):
symfony propel-build-model symfony propel-build-sql symfony propel-insert-sql symfony propel-generate-crud main blog Article symfony propel-generate-crud main category Category symfony cc - because the routing for the static pages will not work with the blog and category modules, add the appropriate entries to apps/main/config/routing.yml:
default_blog: url: /blog/ param: { module: blog, action: list } blog_action: url: /blog/:action param: { module: blog } default_category: url: /category/ param: { module: category, action: list } category_action: url: /category/:action param: { module: category } - also create a view.yml for the blog, for the time being with something like:
Later, I may set this from within the action to make them more appropriate to the pageall: metas: title: Peter Robins - blog description: Peter Robins - blog
Now, tara: the skeleton CRUD should all work; not pretty, but it works. As I'm the only person who will maintain the data, the basic CUD can be kept, but the display templates leave much to be desired, so must be changed to the previous design. As with the Symfony documentation, the article display is much the same in the show and list templates, so can be split out to a partial _article.php, called with <?php include_partial('article', array('article' => $article)) ?>.
Now the actual blog entries have to be copied over, either manually or using a db dump.
Adding blog list by category
The final thing to do is to add the ability to list all the blog entries for a particular category, for example, my walking trips. One of the niftiest features of propel is that it's clever enough to work out the cross-table references and sets up methods in the model to link with other tables. Because category_id was added to the article table, the article base class lib/model/om/BaseArticle.php includes the method getCategory(), which instantiates the appropriate category object. So, if we want the category title rather than the id on our article display, no problem: just use <?php echo $article->getCategory()->getTitle() ?> and there it is.
Similarly, the category base class lib/model/om/BaseCategory.php includes the article-related methods getArticles() and countArticles(). One thing missing from the blog CRUD is the ability to list all articles for a given category. To create this, we'll have a new action category/bloglist with:
- a new function in apps/main/modules/category/actions/actions.class.php:
(in fact, this is the same as executeShow())public function executeBloglist() { $this->category = CategoryPeer::retrieveByPk($this->getRequestParameter('id')); $this->forward404Unless($this->category); } - a new template apps/main/modules/category/templates/bloglistSuccess.php, similar to listSuccess.php but with the category outside the foreach loop
- a new entry in apps/main/config/routing.yml so it can be used. I want to keep this within the blog/ part of the website, so will call it using /blog/category:
blog_category: url: /blog/category/:id param: { module: category, action: bloglist } - you may think that the catch-all we put in the blog view.yml will also apply to the category list, but it won't. The template bloglistSuccess.php is in the category module, not the blog, and as yet we haven't entered a view.yml for that, so create apps/main/modules/category/config/view.yml with something like:
bloglistSuccess: metas: title: Peter Robins - blog category list description: Peter Robins - blog category list
Now, we just call /blog/category/1 or whatever to get our cross-table list of blog entries for a particular category. The links in the menu can be changed to something like <?php echo link_to('May 2007', '@blog_category?id=2') ?>
We've set up the url /blog/category/:id so should also cater for someone trying '/blog/category/'. You could set up routing.yml to give a default id, but instead we'll adapt the template for /category/, which we defined above as /category/list/, i.e. apps/main/modules/category/templates/listSuccess.php, to include a link to the appropriate /blog/category/:id instead of just a display of fields in the category table <?php echo link_to($category->getId(), '@blog_category?id='.$category->getId()) ?>. Then add another entry to routing.yml to send '/blog/category/' to that:
blog_categorys:
url: /blog/category/
param: { module: category, action: list }
There's quite a steep learning curve with Symfony at the beginning, but once you get used to it, it's surprisingly fast to create a simple blog application like this.