Our big problem is that there are paths like node/12345/edit. To handle these and others, we use a wildcard: the percent sign. So, when the system tries to find which {menu_router} entry specifies node/12345/edit it will look at the menu definitions of the following paths:

  • node/12345/edit
  • node/12345/%
  • node/%/edit
  • node/%/%
  • node/12345
  • node/%
  • node

These we call the ancestors of node/12345/edit.

Fit

As a wildcard is less specific than the path itself -- for example, if we defined a {menu_router} entry for node/12345/edit it will only deal with this one node only but node/%/edit deals with all nodes. We can say that node/12345/edit is a better fit than node/%/edit.

So let's add fitness number to these paths:

Path Fitness Fitness in binary
node/12345/edit 7 111
node/12345/% 6 110
node/%/edit 5 101
node/%/% 4 100
node/12345 3 11
node/% 2 10
node 1 1

I think it's quite visible that if we replace the % wildcard with 0 and the specific part with 1 then we get the binary number. We will use this both ways: we can calculate the value fitness of any path easily and also we can generate the ancestors of any given path by generating these binary numbers and replacing backwards.

CSS designers will recognise fitness as being analogous with specifity in CSS selectors.

Ancestors and fitness are used only on run time, not on build time.

Note

An additional optimization has been implemented, so that only the ancestors which correspond to the binary patterns of paths that actually exist in {menu_router} are checked. This is important because the number of possible ancestors increases exponentially with the number of parts in the path. The patterns that are known to exist are called the "masks".

Wildcard vs. Fitness

The right wildcard in these examples can also be %node, rather than %. Using %node gets you a node_load() for free passed into your page callback. However, it does not help calculate fitness.