Developer Style Guide

This page covers rules and styles to be used when submitting code for inclusion in pfSense.

Developer Rules

  • Never commit untested code.
  • If you break the code, you fix it. Period. Even if your code breaks another subsystem. Your code caused the fallout. Yes this is not glamorous but it is the right thing to do (or back your code out until a proper fix can be obtained).
  • If you commit a kernel change that requires a userland configuration change of any type, then you also must make sure there is PHP code to control the userland change as needed (different sysctls, different means of configuring something, upgrade code etc.).
  • Avoid changing the XML configuration structure whenever possible. Where that is infeasible, do not commit code that changes the XML configuration structure without adding configuration upgrade code at the same time.
  • Never commit anything to any branch that knowingly causes a regression.
  • Any major or high risk changes must first be done in a git clone and reviewed by another committer before merging into mainline. Using a pull request for this workflow is acceptable, and is how every change from those outside the core development team is handled.
  • Pre-commit authorization isn’t used in pfSense except in the case of major changes. For external/community developers, pull requests serve this function.
  • Mention relevant ticket numbers in commit messages so that Redmine can associate the changes. See Referencing Tickets in Commit Messages.
  • When possible, compose and format commit messages similar to entries in the change logs. For example:
    • Brief first sentence that describes the commit
    • Start with an action word describing the nature of the change (“Adds…”, “Changes…”, “Improves…”, “Corrects…”)
    • Reference the ticket number in the first sentence (see previous bullet point)
    • Examples: “Change X to Y which fixes #1234”, “Correct check for XYZ in some_page.php to prevent badthing. Fixes #2345”, or “Add coolnewthing to some_page.php. Implements #3456”
    • Longer, more detailed explanations can be placed on the next line and later.
  • Always use full paths when calling an executable (e.g. “/usr/bin/grep” NOT “grep”)

HTML Specific Rules

Note: Incorrect HTML code is treated as broken code. To break the code isn’t allowed. A C compiler for example would complain in most cases if you break the code syntactically. Most browsers may ignore invalid code, but this does not mean that the code is not broken or that it must be fixed by the person who committed the invalid code.

pfSense uses the XHTML doctype in its webGUI code. The doctype enforces code against the following ruleset:

  • Use lower case tag names and not a mix of uppercase and lowercase tag names
  • Breaks must be closed (<br />)
  • Image tags must be closed (<img />)
  • An image tag always has an alt attribute, though it may contain no value
  • Horizontal rule tags must be closed (<hr />)
  • HTML form fields must be closed (<input />)
  • Ampersands in a URL (e.g. within a href attribute) must be coded as a HTML entity (e.g. &)
  • Special characters (e.g. umlauts) must be coded as HTML entities. see:
  • A <table /> tag does not have a name attribute
  • A <div /> tag does not have a name attribute
  • A <ul /> tag does not have a name attribute
  • A <li /> tag does not have a name attribute
  • Checkbox checked attributes must be coded as checked=”checked”
  • HTML field disabled attributes must be coded as disabled=”disabled”
  • HTML field readonly attributes must be coded as readonly=”readonly”
  • Any HTML <input /> field has a type attribute (e.g. type=”text”)
  • Opening <p>, <b> tags must have a matching closing tag (e.g. </p>)
  • <table /> tags do not contain a <form /> tag
  • Place the inputerror <div /> after the “tabnavtbl” < td />, before the “mainarea” <div />
  • Place the “iform” <form /> tag right before the “tabcont” <table /> tag
  • There’s no reason to include the inputerror <div /> twice within the same HTML file
  • The “type” attribute of a <form /> tag needs to contain a lower case value (e.g. type=”post” or type=”get”)
  • The language=JavaScript attribute for <script /> tags is deprecated. Use the type=”text/javascript” attribute instead.
  • Always use lowercase attribute names for calling JavaScript events (e.g. onclick=”foobar();”)
  • The <embed /> tag is deprecated use <object /> instead
  • If a style attribute is assigned to an HTML element it needs to be enclosed by quotes, for example: = “2px solid #990000”;

It is possible to syntax check code in Firefox with the HTML validator plugin. Or you can simple use the W3C validator. The latter is supported by Opera even for RFC 1918 networks.

PHP Specific Rules

Rule #1: Any time a rule is broken, there must be proper justification and documentation.

General rules

  • All php files must start with a header block in English

  • Use descriptive variable names in English

  • Use lowercase variable names ($my_very_long_var_name) or Camel Case names ($myVeryLongVarName)

  • When referencing variables inline in double quoted strings, use braces around the variable names:

    $foo = "bar{$bar}bar";
  • Add comments in English, whenever necessary or helpful

  • Use // or /* */ style syntax for single line comments, do not use #

  • Use /* */ style syntax for multi-line comments

  • Use elseif and not else if when given a choice. The else if variant only works with braced syntax and not colon syntax (e.g. if: ... elseif: ... endif;).

  • For testing the same variable against multiple strings or values directly, use a switch statement rather than a long chain of if/elseif/elseif/elseif/.../else statements.

  • Add TODO: comments, when there is something to be done

  • Add FIXME: comments, when something is broken

  • add NOTE: comments, when there is something important other people should know beyond a traditional comment, for example a warning about not changing code in certain ways.

  • Try to code in a readable way:

    $header = "<head>{$foo}</head>";
    $message = "SOME{$bar}TEXT";

    Is easier to read than:

    $message = "SOME" . $bar . "TEXT";
  • Try to simplify code for better readability:

    if ($bool1)
       if ($bool2)
           if ($bool3)
  • Should be written as:

    if ($bool1 && $bool2 && $bool3)
  • Do not set unnecessary variables:

    $is_set = isset($var);
    if ($is_set) ...
  • Loop variables are $i, $j, $k, …

    • Do NOT use $g for a loop variable, as it conflicts with the global $g used by pfSense
  • All switch statements must have a default

  • In classes, use private, protected and public, not var for attribute declaration

  • Do not to use deprecated or obsolete functions

    • Keep an eye on future versions of PHP to avoid using functions that will be deprecated in the future as well
  • If a PHP-internal function is an alias for another function, use the original (i.e. use exit() instead of die())

Indent style

  • Use “K&R, BSD KNF variant style” (see ):

    if ($x == $y) {
    } else {
  • When creating if, for, foreach, and other similar block style structures, even if there is only one statement inside, the use of braces is strongly recommended for clarity.

    For example, good:

    if ($foo) {

    Not so good::

    if ($foo)
  • If a conditional statement must span multiple lines, indent using four spaces to align with the start of the conditional above it:

    if ($foo1 && $foo2 && $foo3 && $foo4 && $foo5 && $foo6 &&
        $foo7 && $foo8 && $foo9) {
  • There should not be a space between a function name and its argument list:

  • … but separate function arguments with a single space:

    do_something($foo, 27, false);
  • Use tabs for indentation (not spaces or a mixture of both)

  • Use a tab stop of 8, rather than 4

  • … but use spaces in the middle of a line and for long conditional alignment

  • Ensure there is NO trailing whitespace at the end of a line, for example spaces or tabs when there is no more text afterward

  • Ensure there is NO whitespace on empty lines. For example, a line must not contain only spaces or only tabs

Configuration Manipulation

  • Boolean values which are false should be un-set:

    $config['system']['enablesshd'] = "no";

    should be:


Shell Script Specific Rules

  • Use braces in all variable references for proper parameter expansion, such as:


Ports/Packages Specific Rules

When working with the pkg system and FreeBSD ports structure, adhere to the FreeBSD guidelines for code in these files.

Useful resources for working with pkg and ports include:

Other Guidelines:

  • A port version or revision must increase for the port to be rebuilt, otherwise changes will not propagate to the pkg servers to be picked up by clients
    • For very minor changes, add or increase the PORTREVISION line beneath PORTVERSION in the makefile, starting at 1, for example: A second revision would be PORTREVISION=2
    • For more significant changes, increase PORTVERSION
      • When increasing PORTVERSION, completely remove any PORTREVISION line, do not comment it out
    • Do not add or change PORTEPOCH except under direction of a committer

External Code

Code that has been imported from an external source does not need to be changed to fit these guidelines, for example modules for IPv6, CHAP, simplepie, and so on.

Editor Configuration

The pfSense project uses a similar coding style to FreeBSD, which has editor configurations for Emacs and Vim available at . See also