home resources search newsjoinmembers: 6958
PHP Flash Java Ruby Windows Linux
Hiveminds's picture

Hiveminds | Thu, 2006-11-23 13:18  tags: , ,

The PHP documentation states quite clearly that function names in PHP can be alpha-numeric as long as they start with an underscore character or letter. So why don't PHP developers use numbers?

One of the problems with using procedural code in PHP is naming functions. If you have hundreds of functions then you are going to run into naming problems after a while. In PHP function names, not protected by OOP classes, have to have unique names. This is no problem if you are not using a hook system like that of Wordpress and using OOP where necessary. But in a CMS like Drupal where the module file is used as a psuedo class container this is harder to work with. The Drupal CMS is coded using the underscore character as a designation for a callback or "hook" system. This "hook_action" is an example. Well, as the project grows and becomes more popular then you start running out of humanly understandble words and letters to use. That or the names become too long to be remembered during normal development. Naming conflicts occur more and more often. This is where the use of numbers in the name of functions becomes the answer.

The numbers game

Numbers can be used in a memorable fashion and have a lot more variations. Nemonic and phonetic tools like those used for beauty license plates are a good option.
 

There are many ways to use numbers in a hook system but my favorite is what I like to call tying the knot. It looks like this "_0_". Other examples are _8_, _83_... I could go on but you get the idea. An underscore followed by a number and then another underscore. The naming convention for the hook usage or scanning loop is [a-zA-Z]_[0-9]_[hook name]. This makes the regular expression check for proper usage simple. Though two digits should be enough for most it is scalable. The only thing to be remembered is the fact that 0-9 is not the same as 00-09. The number of spaces a number takes is also part of the rules of what we will call a namespace system from this point.

<?php

/**
 * Determine whether a module implements a hook.
 *
 * @param $module
 *   The name of the module (without the .module extension).
 * @param $hook
 *   The name of the hook (e.g. "help" or "menu").
 * @return
 *   TRUE if the module is both installed and enabled, and the hook is
 *   implemented in that module.
 */
function module_hook($module$hook$namespace='') {
  
// check for $namespace key in loaded functions
   
$module_arr explode("_",$module);
   
$namespace = (int)$module_arr[0];
   
$module $module_arr[1];
   if(
is_int($namespace){
     return 
function_exists($module .'_'.sprintf("%02d",$namespace).'_'$hook);
   }
   else
     print 
"developer embarassed. sorry";
   }
}
?>

You may have noticed that I did not use the modules name to create the namespace. Why this is done is explained a bit further down.

Filesystem and Array friendly

Using numerical naming makes arrays and the OS filesystem your friends. Set up properly the names of files are preordered in the filesystem and conversion to a sortable array becomes easier.
 

In Drupals and possibly Wordpresses module loading system You  call files in the order that they should be called alphabeltically or by weight and not worry about function loading conflicts.

Since the english alphabet only contains 26 letters you get weird hierarchial problems with files after a certain point. So although you could get 17,000+ variations using the alphabet, it is not as readable,memorable and does not carry as much order as using numerical values. The naming convention of the files or directories themselves would actual change so that they have numerical sequence. In the case of Drupal a normal module list would be:

page
pagination
path
ping
poll
profile

Drupal version 4.6 used the default a-z array sort to determine the order in which module files get loaded. I dislike this very much and the newer system in version 4.7, using weights in the database is equally distasteful. But using numerics you can set the loading sequence as needed. As mentioned Drupal gets its function names from the module file name. So we will use it as an example case. The Drupal system can be further enhanced by making the module file act more like a class container by using the numerical key to strictly enforce a namespace.

09_page.module
08_pagination.module
07_path.module
06_ping.module
05_poll.module
04_profile.module
03_locale.module
02_menu.module
01_node.module
00_system.module

Another nice thing about using numerics is that they can resolve file naming conflicts. If two files want to be called "view_helper" then they can be because the namespace system described here will ignore the alphabetic tags on the files and the OS will just order them. An example:

03_view_helper.module
04_view_helper.module

Of course the developers may want to argue who gets what number but that will not effect the outcome in the system.

An outside contribution is also inhibited from conflicting with core module files and earlier established contributions. If a new core hook is added there is no danger of it conflicting with a contributed modules functions because core hook names and function name prefixes are not allowed to have numerical values only the set namespace (the file containing the code).

Resolving conflicts

Function names conflicting between module files are a common occurance when reusing code or integrating third party software. Numerical namespacing makes conflicts impossible within the system and more improbable for third-party name conflicts.
 

If a developer wants to borrow code from another file they are forced to add a new or different namespace for the function to work in their module file as a global to the system. Normally having "system_locale()" in two different files would result in a function already loaded error.

You enforce a namespace rule strictly by throwing an error if a contributed module file tries to load a hook function without a numerical key in its name.

<?php
function name_hook(){
// this will throw an error if in anything but a core module
}
?>

<?php
function name_01_hook(){
// this is allowed
}
?>

<?php

static $files = array();
if (
$files[$type][$name]) {
return 
TRUE;
}
$filename drupal_get_filename($type$name);
if (
$filename) {
   include_once(
$filename);
   
// check for $namespace key in loaded functions
   
$namespace_arr explode("_",$filename);
   
$namespace $namespace_arr[0];
   
$arr get_defined_functions();
   
$listed $arr['user'];
foreach(
$listed as $value){
   if (!
strpos($valuesprintf("%02d",$namespace))){
    print 
"angry error message.";
   }
}
$files[$type][$name] = TRUE;
return 
TRUE;
}
return 
FALSE;
}
?>

In cases where the software being developed is a collaboration of contributions, a developer or group can be given a number or key to use as its namespace. This system works very well in Typo3 which has hundreds of contributed extensions to keep track of.

Core changes that are effected by the loading sequences of modules are less likely to happen and much easier to resolve. This is because prefixing would maintain the numerical sequence and not effect the main order of things. An example would be if a system module needed to be enhanced by a previously contributed module but it has to be loaded before and after certain files.

This is also why earlier I told you that 0-9 is not the equivalent of 00-09 in the system. Strict adherance to this rule will eliminate any conflicts in ordering.

This also means a little forethought is necessary when choosing the number of namespaces that will be needed over time. Though it is very easy to scale out by adding a digit space to the system, it is better to allow more space than you need beforehand. In a extension library like Typo3's, where the number of contributions is 1200+, a five place key should cover the mark. But doing six places is best.

00_system.php
001_system_ajax.php
001_system_path.php
01_node.php
02_menu.php
03_locale.php

So why do you want to control the number of decimal places used? Well, because then by adding a place after the set number of spaces you get a Public (globally available functions) and Private (local to the file and any helper files) area for each Namespace. In the above example only 00_system can call the functions in 001_system_ajax.php or 001_system_path.php because only the module files using two digits as namespace would be loaded. No hooks can be called in these files they are strictly helpers to the main module. Trying to do so would violate two rules. The first being loaded modules have to have only two digit keys and the second being hooks can only be used within files that have two digit keys. Files using three spaces would hidden from the function that loads all files/modules.

Changing the rules

Cooking without recipes only works for professionals. Mostly everyone else needs rules, recipes and guidelines to follow. They not only need them but appreciate that they exist.
 

Though Wordpress has some rules about how a plugins functions should be named they are not really enforced and come under the heading of "suggestion" or "best practice". Drupal has no rules. The lack of rules has to be changed. CMS project developers and PHP developers in general are going to have to start thinking about how to get along with the ever growing Standard PHP Library and its 4000 or so names along with dozens of popular PHP frameworks including that of Zend. This will not be possible without setting in writing what the guidelines for development "have" to be!

Hiveminds's picture
This article brought to you by the Hiveminds Magazine - Staff. Contact us if you want to post an article or announcement anonymously
Thoughtbox - So what did you think?



maskd - posted on: Thu, 2006-05-18 12:20.

A good read, I enjoyed it, but doesn't the English language have 26 letters in it ;)

Hiveminds posted on: Thu, 2006-05-18 15:07.

I am not quite finshed with the article but I don't think a spellchecker would have caught that! Thanks.

 
CMS Comparison Matrix
 
Windows Wordpress Adobe Flex PHP eRuby Adobe Flex Silverlight Adobe Flex eRuby

Newsletter

Get updates on Hiveminds services, articles and downloads by signing up for the newsletter.

Editor's choice

Some of the better articles, stories and tutorials found at Hiveminds.

Find more

Find more of Hiveminds articles, stories, tutorials and user comments by searching.




Picked links

Hand picked websites and articles from around the web that provide quality reading.