Peter Robins, his website

Setting up this site in Symfony

Phase 4: adding db-based pages; 3: caminos

The final mini-app is the Caminos de Santiago database. This poses few problems; it is also stored in an SQLite 3 file, and has to be converted; it only has 1 table, keyed on an id which is an adapted form of the name of the route; again, the data is all maintained by me, so there's no need for CUD. Only two pages use the database: for displaying a list of the routes, sorted by id and with the Compostelan routes separated out from the other routes; and the details of a route. The rest, of which there are many, are static files which need to be converted.

Prelims: routing, new db, new module, meta entries
  1. routing: the only page that needs to be entered in apps/main/config/routing.yml is the routes page, but we'll also make it so that 'routes/' should show the routelist page, and for backwards-compatibility we'll allow ':route.' - i.e. the route name without the .html suffix - and routelist:
    camino_routes:
      url:   /camino/routes/
      param: { module: camino, action: list }
    
    camino_route:
      url:   /camino/routes/:route
      param: { module: camino, action: route }
    
    camino_route2:
      url:   /camino/routes/:route.
      param: { module: camino, action: route }
  2. as with flights, we have to add the db to config/databases.yml, create a new module - caminos - and create a view.yml for the module. We then convert the db, and generate the schema and the model.
  3. actions: apart from executeShow() we need the executeRoute() function which is a simple primary-key read of the caminos peer; again, as this is parameter-driven, we have to allow for false ones. We'll also set the title and meta description dynamically to include the name of the route:
      public function executeRoute()
      {
        if (!$this->route = CaminosPeer::retrieveByPk($this->getRequestParameter('route')))
    	return 'Error';
        $this->getResponse()->setTitle('The Roads to Santiago - '.$this->route->getName());
        $this->getResponse()->addMeta('description', 'The Roads to Santiago - '.$this->route->getName());
      }
    We also need the list function
      public function executeList()
      {
        $c = new Criteria();
        $c->add(CaminosPeer::TYPE, NULL);
        $c->addAscendingOrderByColumn(CaminosPeer::ID);
        $this->compRoutes = CaminosPeer::doSelect($c);
        $c = new Criteria();
        $c->add(CaminosPeer::TYPE, 'other');
        $c->addAscendingOrderByColumn(CaminosPeer::ID);
        $this->otherRoutes = CaminosPeer::doSelect($c);
      }
    
    With 2 reads for the 2 types, this is not the most efficient way of doing things, and if I ever expand the number of types it becomes unwieldy, but it keeps the logic and the template nice and simple
  4. templates: again, we need an Error and Success template for the route page, and a listSuccess, but otherwise the templates are all straightforward. Several templates include a link to an image; this is not well documented on the Symfony site, so here's how to do it: <?php echo link_to('stylised shell', image_path('camino/coquillebleue.jpg', true)) ?>. You have to get the absolute path, or the helper thinks it has to convert it to a url and gets very confused.
    Finally, the 'changes' page has an associated RSS feed, created elsewhere. It would be nice if there were the ability to add the link tag to the header from the view.yml config for that page, but this doesn't seem to be the case, so I simply added an if clause to apps/main/templates/layout.php:
    <?php if ($sf_params->get('module') == 'camino' and $sf_params->get('page') == 'changes'): ?>
    <link rel="alternate" type="application/rss+xml" title="Caminos de Santiago - Changes" href="../files/camino/changes.rss" />
    <?php endif; ?>
    This seems a bit of a kludge. You could, I suppose, have a special layout just for this page, but that seems excessive. So if anyone knows of a better way . . .

February 2008