New in b5: Improved route flexibility

Rather than using this blog solely for announcing new releases, I think I’ll start posting more details on new features and how the backend of Chyrp works as it evolves. So, we’ll start with a change to the “custom routes” system that I just pushed to the repository last night.

The “routes” setting is a humble little powerhouse residing in /includes/config.yaml.php that is shrouded in mystery to anyone who hasn’t used it when developing a Module. Its original purpose was to allow Modules to easily provide their own routes for when the user has clean URLs on. For example, the Tagginator module adds a tag/(name)/ route setting, which meant “when the visitor goes to /tag/foobar/ in their browser, set the Route->action to ‘tag’ and set $_GET[‘name’] to ‘foobar’”.

Here’s what it looked like:

routes:
  - tag/(name)/

This setting was managed by calling Route->add(“tag/(name)/”)1, and Route->remove(“tag/(name)”) to remove it when uninstalling the module.

In beta 5, custom routes go one step further by allowing you to specify an action for any route. For example:

routes: # The beginning and trailing slashes are optional.
  tag/(name)/: tag
  unfinished: drafts

The first setting is the new form of the same setting from the Tagginator module in b4 and under. The second is a superfluous route I just threw in for an example. unfinished: drafts means “if they’re at /unfinished or /unfinished/, set the Route->action to ‘drafts’”. It essentially “clones” the /drafts/ page to /unfinished/.

If you wanted, you could view tags like /this-is-a-tag/ just by doing this2:

routes:
  (name): tag

There isn’t a risk of overriding other pages this way, as every custom route now calls an optional “check_route_[action]” trigger that checks if that Route should be used or not. In this case, a check_route_tag callback was added to the Tagginator module, so if there isn’t a tag at /(name)/ it will tell the Routes parser by returning false, and it will continue trying other routes instead. If there is a tag, it will return true, and the Routes parser will set the Route->action to ‘tag’ and $_GET[‘name’] to ‘this-is-a-tag’.

All of the examples above are only useful to those with “Clean URLs” enabled, but if you have .htaccess support and you have it disabled for some reason, you could just as easily do something like this:

routes:
  ?action=unfinished: drafts

If you’re a module developer, the only change you’ll have to make is adding a second argument to your Route->add function for the action the path points to.


  1. This is the syntax I use when describing things instead of Route::current()->foo(), just for the sake of legibility. Technically I could say $route->foo() but that doesn’t feel right to me as a programmer, since $route isn’t always used. ;) 

  2. Though you would still have to modify the URLs used in the module and your theme’s sidebar.