Summary: use categories as tags
Prerequisites: PmWiki 2.x
Status: stable
Version: 2021-09-19
License: GPL
Maintainer: sts
Categories: Links CMS Blog PIM PHP72
Users: +2 (View / Edit)

Questions answered by this recipe

  • How do I use PmWiki's builtin categories like tags?
  • How do I list all referenced categories?
  • How do I make the HTML meta keywords tag to include all the tags of a wiki page?
  • How do I make a tag cloud on my website?


PmWiki supports the [[!Category]] syntax to sort pages into categories. As Category.CategoryName pages do not need to exist (and in fact normally don't), pagelist cannot be used to list all referenced categories. Moreover pagelists have no way to list linked pages at the moment. So this recipe implements a simple custom markup to add this feature: (:listcategories simple (Main|Blog|Pics)\..*:).

To speed up tag listing the .pageindex file is used (which is created by pagelist.php anyway, so the speed penalty is nearly non-existant (in contrast to the tags recipe, which iterates over all pages all the time).

This recipe also alters the format of category links in the HTML output into something like <a class='categorylink' rel='tag' href='\$LinkUrl'>\$LinkText</a>. So Technorati and other sites will recognize PmWiki's categories as tags.



Just put

(:listcategories simple (Main|Blog|Pics)\..*:)

into your sidebar, footer or whereever. The regular expression tells the script which pages should be considered to look for categories. E.g. in the PmWiki documentation some categories are used which should be excluded in my setup.

The keyword "simple" is a key for the $ListCategories_MarkupFunctions array which is a list of possible markup functions. "simple" will give a simple space separated list, "sized" gives you the layout you see in the picture above with different font sizes. If you want another layout, just do something like that in your local config.php after including the recipe:

$ListCategories_MarkupFunctions["yourlayout"] = 'YourLayoutFunction';
function YourLayoutFunction( $categories ) {
  $out = "";
  $space = "";
  foreach( $categories as $pn => $count ) {
    $out .= $space . "[[Category.$pn|$pn]]";
    $space = " ";
  return PRR($out);

Then you can write in your wiki pages: (:listcategories yourlayout {$FullName}:).

You can also list the categories of a page by putting the following into the GroupFooter page:

Tags: (:listcategories simple {$FullName}:)

You can set the following variables in config.php, they will override the default values, shown below:

$ListCategories_CreatePages = true; # automatically create Category.Bla pages?
$ListCategories_IncludeCategories = "/.*/"; # categories to include
$ListCategories_ExcludeCategories = "/^Blog$/"; # categories to exclude
$ListCategories_SizedlistNum = 30; # max number of items in the SizedList format
$ListCategories_SizedlistMinFontSize =  8; # minimal font size
$ListCategories_SizedlistMaxFontSize = 26; # maximal font size
$ListCategories_SortSizedList = false;  # sort the tag cloud alphabetically
$ListCategories_SortSimpleList = false; # sort the simple list alphabetically

The first one makes the script to create the references category pages. That's useful to avoid those ugly "?" at links to non-existant pages. The next two are regular expressions. Look here for an explanation. Basically ^ matches the beginning, $ the end of a line. The dot . matches any character, the * means that the previous character is repeated as often you want (also zero times). With the | you can define alternatives, e.g.

$ListCategories_IncludeCategories = "/^(Blog|Main)$/";

to match only those two categories.

It is possible that PmWiki's pageindex (used for caching page meta data) is incomplete. PmWiki updates it on every edit, but still it can be incomplete in certain circumstances. This recipe adds the action "pageindex" to create a complete new index (might take several seconds). Just go to your site and append "?action=pageindex" to the url. Do that everytime your category list is incomplete.


  • This recipe will not work if you disable the page index via $EnablePageIndex=0.

Release Notes

  • 2021-09-19 - XES: fixed PHP warnings about undefined constants. The $ListCategories_MarkupFunctions values needed quotes around the function names.
  • 2017-09-23 Adjusted recipe to meet PHP 5.5-7.1 compatibility standards, changed version numbering to date-based. XES
  • 2007-02-05 Added minimal and maximal font size for sized list
  • 2006-11-26 [[!foo|foo]] doesn't exist. Only [[!foo]]...
  • 2006-11-25 Added options to sort the category list alphetically
  • 2006-11-25 include rel='tag' as described in
  • 2006-11-13 $RecipeInfo line
  • 2006-10-15 $ListCategories_SizedlistNum variable. See above.
  • 2006-10-13 added "include" style to include all category pages. This is useful if your category pages only include (:keyword ...:) tags. So your tagged pages will get proper html meta tags for keywords, useful for search engines... Just include (:listcateories include {$FullName}:) into your PageFooter page and fill the categories pages with (:keywords Your,Own,Keywords:) lines. The auto-create feature of this recipe sets the pagename already as the first keyword. (To make use of this for an old installation of this recipe, delete your category pages. The recipe will recreate them. Then update your index with the ?action=pageindex action).

If the recipe has multiple releases, then release notes can be placed here. Note that it's often easier for people to work with "release dates" instead of "version numbers".


Please see ListCategories-Talk

  • It's throwing 3 php Warn errors for use of undefined constants on 4 lines. Clogging up the logs. Going to look at it, but haven't done much programming in years. (Edited: now fixed and uploaded.) XES September 19, 2021, at 07:47 PM

See Also



See discussion at ListCategories-Talk

User notes +2: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.