

1. Ü B E R S I C H T
Umfang
Dieses Dokument stellt die Coding-Standards und Programmierrichtlinien für den professionellen PHP-Entwickler und Entwickler-Teams bereit. Die Hauptthemen sind:
– Allgemeine Grundsätze
– Dateiformatierung
– Namenskonventionen
– Programmierstil
– Inline-Dokumentation
– Musterklasse
Vorteile
Gute Programmierstandards sind wichtig für jedes Software-Projekt, insbesondere wenn mehrere Entwickler zusammen an einem Projekt arbeiten. Coding-Standards verhelfen zu einem qualitativ hohen und einheitlichen Code mit weniger Fehlern und einfacher Wartung.

2. A L L G E M E I N E G R U N D S Ä T Z E
– Jede Funktion oder Methode erfüllt nur einen Zweck, den aber möglichst gut.
– Alles ist objektorientiert.
– Alles wird in Englisch verfasst.
– Alles ist für den phpDocumentor dokumentiert.
– Alles ist so kurz wie möglich gehalten.
– Alles ist so zeitlos wie möglich.

3. D A T E I F O R M A T I E R U N G
Allgemeines
Bei Dateien, die nur PHP-Code enthalten, ist der Abschlusstag ("?>") wegzulassen. Von PHP wird dieser nicht benötigt und verhindert so unerwünschte Leerzeichen beim finalen Output.
Einzug
Benutze einen Einzug von vier Leerzeichen ohne Tabulatoren. Editoren sollten so konfiguriert sein, dass Tabulatoren als Leerschläge ausgegeben werden um Tabulatorzeichen im Quellcode zu vermeiden.
Maximale Zeilenlänge
Die optimale Zeilenlänge ist 80 Zeichen; d.h., Entwickler sollten so nah wie möglich an der 80 Zeichen Grenze bleiben, soweit dies praktikabel ist. Längere Zeilen sind aber erlaubt. Die maximale Länge einer Zeile mit PHP-Code beträgt 120 Zeichen.
Zeilenabschluss
Zeilenbegrenzung ist der normale Weg für Unix Textdateien. Zeilen müssen mit einem Zeilenvorschub (LF) enden. Zeilenvorschübe werden durch eine ordinale 10, oder durch 0x0A (hexadezimal) dargestellt. Benutze kein Wagenrücklauf (CR) wie bei Macintosh (0x0D). Benutze nicht die Kombination aus Wagenrücklauf und Zeilenvorschub (CRLF) wie bei Windows (0x0D, 0x0A). Jede Zeile darf am Schluss keine Leerzeichen enthalten. Editoren können so konfiguriert werden, dass Leerzeichen am Ende einer Zeile automatisch entfernt werden.

4. N A M E N S K O N V E N T I O N E N
Verwendete Abstraktionen der API (Class Interfaces)
Wenn eine API für Softwareentwickler erstellt wird und die Softwareentwickler eine Abstraktion anhand der Bezeichnung identifizieren können müssen, trenne die Einzelnen Wörter mit Underscores statt camelCase. Beispiel: Der Name für den MYSQL PDO Driver ist "pdo_mysql", nicht "pdoMysql". Wenn der Entwickler einen String verwendet, muss er diesen kleinschreiben. Wenn es Sinn macht, füge eine Konstante dazu ein (z.B. PDO_MYSQL).
Klassen
Die Benennung von Klassen in einem Framework sollten grundsätzlich ein Abbild der Verzeichnisstruktur eines Frameworks sein. Das Hauptverzeichnis eines Frameworks wird mit dem Namen des Frameworks angegeben z.B. "Buxa/". In diesem werden dann alle Klassendateien hirarchisch abgespeichert.
Klassennamen dürfen nur alphanumerische Zeichen enthalten. Zahlen sind erlaubt, jedoch zu vermeiden. Underscores sind nur an der Stelle des Pfadseperators erlaubt. Zum Beispiel der Datei mit dem Pfad "Buxa/Db/Table.php" muss die Klasse "Buxa_Db_Table" enthalten.
Wenn ein Klassenname aus mehreren Wörtern besteht, wird der erste Buchstaben von jedem neuen Wort grossgeschrieben. Aufeinanderfolgende Grossbuchstaben sind nicht erlaubt; z.B. die Klasse "Buxa_PDF" ist nicht erlaubt, "Buxa_Pdf" aber schon.
Die Klassen, die zu einem Framework gehören müssen immer mit dem Namen des Frameworks beginnen. Bsp: Klassen welche mit "Buxa_" beginnen, werden im Ordner "Buxa/" hirarchisch abgelegt. Hier ein paar gültige Klassennamen:
Buxa_Db
Buxa_Db_Table
Buxa_Controller
WICHTIG: Klassen welche mit dem Framework kommunizieren, jedoch nicht Bestandteil des Frameworks sind, z.B. vom End-User geschriebener Code, dürfen niemals mit dem Frameworknamen; z.B. "Buxa_" beginnen.
Schnittstellen
Schnittstellenklassen müssen denselben Namenskonventionen der normale Klassen folgen (siehe oben), müssen jedoch mit dem Schlüsselwort "_Interface" enden. Hier einige Beispiele:
Buxa_Log_Adapter_Interface
Buxa_Controller_Dispatcher_Interface
Dateinamen
Für alle anderen Dateien dürfen nur alphanumerische Zeichen, Underscores und Trennstriche ("-") verwendet werden. Leerzeichen sind nicht erlaubt. Jede Datei, die PHP-Code enthält muss die Endung ".php" haben. Bsp: Diese Dateien sind das Abbild der obigen Klassenbeispiele:
Buxa/Db.php
Buxa/Db/Table.php
Buxa/Controller.php
Funktionen und Methoden
Funktionsnamen dürfen nur alphanumerische Zeichen enthalten. Zahlen sind erlaubt, jedoch zu vermeiden. Underscores sind nicht erlaubt. Funktionsnamen müssen immer mit einem Kleinbuchstaben beginnen. Wenn eine Funktion aus mehreren Namen besteht muss der Anfangsbuchstabe von jedem neuen Wort grossgeschrieben werden. Diese Benennungsmethode wird auch "studlyCaps" oder "camelCaps" genannt. Funktionen und Methoden müssen so klar wie möglich bezeichnet werden, damit anhand des Funktionsnamen jeder versteht was die Funktion macht. Hier ein paar Beispiele für gültige Funktionsnamen:
filterInput()
getElementById()
addAttachement()
In der objektorientierten Programmierung sollten alle Klassenvariablen mit den Suffixen "get" oder "set" in den Methoden verwendet werden. Wenn Design Patterns, wie Singleton oder Factory Patterns, verwendet werden, sollte der Methodenname den Pattern-Name enthalten, damit das Pattern beim lesen verständlich ist. Auch wenn Funktionsnamen keine Underscores enthalten dürfen, müssen als "private" oder "protected" deklarierte Methoden mit einem einfachen Underscore beginnen. Hier ein Beispiel:
class Buxa_Foo
{
protected function _fooBar()
{
// ...
}
}
Zusammenhangslose Funktionen ("floating functions") sind in einer abstrakten Klasse unterzubringen und als statisch zu bezeichnen.
Variablen
Variablennamen dürfen nur aus alphanumerischen Zeichen bestehen. Underscores sind nicht erlaubt. Zahlen sind erlaubt, jedoch zu vermeiden. Klassenvariablen, welche mit "private" oder "protected" deklariert sind, müssen mit einem einfachen Underscore beginnen. Dies ist der einzige Fall, in dem ein Underscore im Variablenname vorkommen darf. Klassenvariablen, welche als "public" deklariert sind dürfen niemals mit einem Underscore beginnen. Beispiel:
class Buxa_Foo
{
protected $_bar;
}
Wie bei den Funktionsnamen müssen alle Variablen mit Kleinbuchstaben beginnen und der "camelCaps" Namenskonvention folgen. Variablennamen sind so kurz und so verständlich wie möglich zu halten. Variablen wie "$i" und "$n" dürfen nur bei kleineren Loops verwendet werden. Wenn ein Loop mehr als 20 Zeilen hat, muss der Zähler ("$i" oder "$n") genauer bezeichnet werden. Bsp: "$fooBarCounter".
Konstanten
Konstantennamen dürfen nur aus alphanumerischen Zeichen und Underscores bestehen. Zahlen sind erlaubt in, jedoch zu vermeiden. Konstanten müssen immer in Grossbuchstaben geschrieben werden. Um die Lesbarkeit zu erleichtern, werden die einzelnen Wörter mit Underscores getrennt. Zum Beispiel, "EMBED_SUPPRESS_EMBED_EXCEPTION" ist erlaubt, aber "EMBED_SUPPRESSEMBEDEXCEPTION" ist nicht erlaubt. Klassenkonstanten müssen als "const" definiert werden. Allgemeine Konstanten, die mit "define" definiert werden, sind nur in Ausnahmefällen erlaubt.

5. P R O G R A M M I E R S T I L
PHP Code Abgrenzung
PHP Code muss immer mit den folgenden Tags abgegrenzt werden:
<?php
?>
Bei Dateien, die nur PHP-Code enthalten, muss der Schlusstag "?>" weggelassen werden (siehe Kapitel 3). Die Kurzvariante "<?" darf nie verwendet werden. Ausgaben wie "<?=$var?>" sind auch nicht erlaubt.
Strings
Ein String sollte grundsätzlich mit einfachen Apostrophen (single quotes) abgegrenzt werden. Dies hat den Vorteil, dass PHP Code im String nicht ausgeführt wird und so z.B. HTML Ausgaben einfacher sind. Nur Datenbankabfragen werden zwischen doppelte Apostrophen (double quotes) gestellt. Stringverbindungen oder Variablen im String werden immer mit dem Punkt als Verbinder geschrieben. Dabei ist vor und nach dem Punkt ein Leerzeichen zu setzen.
// Sample String
$sampleString = 'This is a sample string.';
// Variable Substitution
$welcome = 'Hello ' . $name . ', welcome back!';
// Short SQL Query
$sql = "SELECT name FROM people WHERE id = '" . $id . "'";
// Long SQL Query
$sql = "SELECT id, name FROM people "
. "WHERE name = 'Fred' "
. "OR name = 'Susan' "
. "ORDER BY name ASC "
. "LIMIT 20";
HINWEIS: Alle SQL-Befehle werden immer gross geschrieben.
Arrays mit numerischem Index
Negative Zahlen sind nicht erlaubt als Array Index. Arrays dürfen mit positiven Zahlen als Index beginnen, jedoch ist empfohlenswert jeden Array mit 0 zu beginnen. Wenn die Indexe eines Arrays definiert werden, muss nach jedem Komma ein Leerzeichen stehen:
$sampleArray = array(1, 2, 3, 'Buxa', 'Buxa');
Es ist auch erlaubt, einen Array über mehrere Zeilen aufzuteilen. In diesem Fall muss jede neue Zeile unter dem 1. Element der 1. Zeile beginnen. Hier ein Beispiel:
$sampleArray = array(1, 2, 3, 'Buxa', 'Buxa',
$a, $b, $c,
56.44, $d, 500);
Assoziative Arrays
Bei der Definition von assoziativen Arrays, ist ein Element pro Zeile anzugeben. Dabei ist zu beachten das der "=>" bei allen Zeilen am gleichen Ort steht und somit Schlüssel und Wert untereinander stehen. Die Abstände werden mit Leerzeichen ausgeglichen:
$sampleArray = array('firstKey' => 'firstValue',
'secondKey' => 'secondValue',
'thirdKey' => 'thirdValue');
Die folgende Schreibweise ist auch erlaubt:
$sampleArray['firstKey'] = 'firstValue';
$sampleArray['secondKey'] = 'secondValue';
$sampleArray['thirdKey'] = 'thirdValue';
WICHTIG: Array-Schlüssel und -Wert müssen immer in Apostrophen (single quotes) gesetzt werden!
Klassendeklarationen
Klassen müssen die folgenden Namenskonventionen einhalten. Die geschweifte Klammer wird immer unterhalb des Klassennamens geschrieben ("one true brace" form). Jede Klasse muss einen Dokumentations-Block im phpDocumentor Standard enthalten. Jeder Code innerhalb der Klasse muss vier Leerzeichen eingerückt sein. Es darf nur eine Klasse pro Datei definiert werden. Zusätzlicher Code in einer Klassendatei ist zu vermeiden. In diesem Fall müssen 2 leere Zeilen Abstand zwischen Klasse und zusätzlichem Code gemacht werden. Hier ein Beispiel einer gültigen Klassendeklaration:
/**
* Class Docblock Here
*/
class Buxa_Class
{
// Entire content of class must be indented four spaces
}
Klassenvariablen
Klassenvariablen müssen die folgenden Namenskonventionen einhalten. Alle, in einer Klasse verwendeten, Klassenvariablen müssen innerhalb der Klasse zuoberst aufgelistet werden. Erst darunter folgen die Klassenmethoden. Das "var" Konstrukt ist nicht erlaubt. Klassenvariablen sind immer nach Sichtbarkeit zuzuordnen. Das heisst mit den "private", "protected" oder "public" Konstrukten. Klassenvariablen dürfen als public definiert werden, ist jedoch zu vermeiden. Verwenden Sie die Zugriffsmethoden mit "set" und "get" als Präfix.
/**
* Class Docblock Here
*/
class Buxa_Class
{
/**
* Variable Docblock Here
*/
private $_privateVar = null;
/**
* Variable Docblock Here
*/
protected $_protectedVar = null;
/**
* Variable Docblock Here
*/
public $publicVar = null;
}
Funktionen und Methoden Deklaration
Funktionen und Klassenmethoden müssen die folgenden Namenskonventionen einhalten. Methoden müssen immer zuerst mit ihrer Sichtbarkeit deklariert werden. Das heisst mit den “private”, “protected” oder “public” Konstrukten. Wie bei Klassen, wird die öffnende geschwungene Klammer unterhalb des Methodennamens definiert ("one true brace" form). Zwischen Funktions- oder Methodenname und der Klammer für deren Argumente / Parameter darf kein Leerzeichen sein. Hier ein Beispiel einer gültigen Methodendeklaration in einer Klasse:
/**
* Class Docblock Here
*/
class Buxa_Foo
{
/**
* Method Docblock Here
*/
public function sampleMethod($a)
{
// Entire content of function must be indented four spaces
}
/**
* Method Docblock Here
*/
protected function _anotherMethod()
{
// ...
}
/**
* Method Docblock Here
*/
private function _anotherNewMethod(Array $b)
{
// ...
}
}
HINWEIS: Die Übergabe von Paramentern welche ein Objekt referenzieren, ist nur durch die Definition der Referenzierung in der Funktions- oder Methodendeklaration beim Parameter selbst erlaubt:
function sampleMethod(&$a)
{
// ...
}
Funktionen mit Objekten oder Arrays als Parameter werden folgendermassen deklariert:
class Buxa_Foo
function objectMethod(Buxa_Bar $sampleObject)
{
// ...
}
function arrayMethod(Array $sampleArray)
{
// ...
}
}
Call-time pass by-reference ist nicht erlaubt.
Der Rückgabewert einer Funktion oder Methode dürfen nicht in Klammern gesetzt werden. Dies verschlechtert die Lesbarkeit und kann zudem zu Fehlern führen, wenn eine Funktion oder Methode später eine Referenz zurückgibt.
function foo()
{
// Wrong
return($this->bar);
// Right
return $this->bar;
}
Anwendung von Funktionen und Methoden
Funktionsparameter werden immer mit einem Leerzeichen nach dem Komma aufgerufen. Hier ein gültiges Beispiel eines Aufrufs einer Funktion mit drei Parametern:
threeArguments(1, 2, 3);
Call-time pass by-reference ist nicht erlaubt. Für Funktionen, die Arrays als Parameter erlauben, kann der Array wie folgt auf mehrere Zeilen verteilt werden, damit die Lesbarkeit erhöht wird.
threeArguments(array(1, 2, 3), 2, 3);
threeArguments(array(1, 2, 3, 'Buxa', 'Projects',
$a, $b, $c,
56.44, $d, 500), 2, 3);
if / else / else if
Basis-Kontrollstukturen mit dem "if", "else", and "else if" Konstrukt müssen vor und nach den Klammern mit der Bedingung je ein Leerzeichen haben. Auch die Operatoren müssen mit Leerzeichen am Anfang und am Ende leserlich gemacht werden. Um Blöcke zu gruppieren können zusätzliche Klammern eingesetzt werden. Bei längeren Bedingungen werden alle Bedingungen untereinander dargestellt um die Lesbarkeit zu erhöhen. Die öffnende geschweifte Klammer wird immer auf der gleichen Zeile wie die Bedingung liegt geschrieben. Die abschliessende geschweifte Klammer erhält immer eine separate Zeile. Jeder Code innerhalb der geschweiften Klammern muss vier Leerzeichen eingerückt werden.
if ($a != 2) {
$a = 2;
}
"if" Bedingungen, die "else if" oder "else" enthalten, müssen folgendermassen formatiert werden:
if ($a != 2) {
$a = 2;
} else {
$a = 7;
}
if ($a != 2) {
$a = 2;
} else if ($a == 3) {
$a = 4;
} else {
$a = 7;
}
HINWEIS: Das zusammen geschriebene "elseif" Konstrukt ist nicht erlaubt!
Dreifach konditionaler Operator
Bei sehr kurzen "if"-"else" Konstrukten ist der dreifach konditionaler Operator an dessen Stelle anzuwenden:
$sampleVar = isset($_GET['sampleVar']) ? $_GET['sampleVar'] : '';
switch
Kontrollstrukturen mit dem "switch" Konstrukt muss wie "if", "else" und "else if" vor und nach den Klammern des Switch-Elements ein Leerzeichen enthalten. Code innerhalb der Switchanweisung muss vier Leerzeichen eingerückt werden. Unter dem "case" Element müssen bis zum nächsten "case" Element jeder Code vier Leerzeichen eingerückt werden.
switch ($sampleNumber) {
case 1:
// ...
break;
case 2:
// ...
break;
default:
// ...
break;
}
Das "default" Konstrukt sollte bei einer "switch" Bedingung nie weggelassen werden.
HINWEIS: Manchmal kann es nötig sein ein "case" Element zu schreiben, auf das kein ein "break" oder "return" folgt. In diesem Falle muss folgender Kommentar anstelle des "break" eingefügt werden:
// break intentionally omitted
while / for / foreach
Die "while", "for" und "foreach" Schleifen werden gleich wie "if", "else" und "else if" formatiert.
for ($i=0; $i<10; $i++) {
echo 'Hello ' . $i . "\n";
}
foreach ($sampleArray as $key => $value) {
echo $key . ' is ' . $value . "\n";
}
while ($row = mysql_fetch_assoc($result)) {
echo $row['id'] . "\n";
}

6. I N L I N E D O K U M E N T A T I O N
Formatierung
Alle Dokumentationsblöcke ("docblocks") müssen mit den Konventionen von phpDocumentor übereinstimmen. Mehr Infos dazu unter http://phpdoc.org. Jede Quellcode-Datei für ein Framework muss zuoberst einen "file-level" docblock enthalten. Darauf folgt ein "class-level" docblock oberhalb der Klassendeklaration. Die Raute ("#") darf nicht als Kommentarvariante verwendet werden.
Dateien
Jede PHP-Datei muss im Minimum einen docblock mit den folgenden phpDocumentor Tags enthalten:
/**
* Short description for file
*
* Long description for file (if any)...
*
* LICENSE: Some license information
*
* @copyright 2006 Buxaprojects
* @license http://www.buxaprojects.com/license/1_0.txt Buxa Licence 1.0
* @version $Id$
* @link http://dev.buxaprojects.com/package/PackageName
* @since File available since Release 1.0
*/
Klassen
Jede Klasse muss im Minimum einen docblock mit den folgenden phpDocumentor Tags zuoberst enthalten:
/**
* Short description for class
*
* Long description for class (if any)...
*
* @copyright 2006 Buxaprojects
* @license http://www.buxaprojects.com/license/1_0.txt Buxa Licence 1.0
* @version Release: @package_version@
* @link http://dev.buxaprojects.com/package/PackageName
* @since Class available since Release 1.0
*/
Funktionen
Jede Funktion oder Klassenmethoden muss im Minimum einen docblock mit den folgenden Tags enthalten: Beschreibung, Parameter, Rückgabewerte. Der "@access" Tag ist nicht nötig, weil dieser schon anhand des "public", "private", oder "protected" Konstrukts ermittelt werden kann. Dies gilt auch für den "@abstract" Tag.
/**
* Short description for the function
*
* Long description for the function (if any)...
*
* @param array $array Description of array
* @param string $string Description of string
* @return boolean
*/
Wenn eine Funktion oder Methode eine Exception ausgibt, ist der "@throws" Tag erforderlich:
@throws Exception_Class_Name Description
Variablen
Jede Klassenvariable muss im Minimum einen docblock mit einer Beschreibung und einem Typentag enthalten:
/**
* Description for the variable
* @var array
*/

7. M U S T E R K L A S S E
<?php
/**
* Buxa_Lifeform_Human
*
* Creation and manipulation of human beeings.
*
* LICENSE: Free
*
* @copyright 2006 Buxaprojects
* @license Free
* @version 1.0
* @package Buxa_Lifeform
* @subpackage Human
* @link http://dev.buxaprojects.com/Buxa/Lifeform/Human
* @since File available since Release 1.0
*/
// Buxa_Lifeform
require_once 'Buxa/Lifeform.php';
/**
* Creation and manipulation of human beeings.
*
* This fascinating class provides you to create and manipulate human beeings.
* This class also inherits properties and methods for age, size or weight from
* the parent class Buxa_Lifeform. Most additional properties are declared as
* protected, because there could be some subclasses. Note that this is just
* a sample class and is not created for real usage.
*
* @copyright 2006 Buxaprojects
* @license Free
* @version Release: 1.0
* @link http://dev.buxaprojects.com/Buxa/Lifeform/Human
* @since Class available since Release 1.0
*/
class Buxa_Lifeform_Human extends Buxa_Lifeform
{
/**
* Valid colors for the eyes
* @var array
*/
static private $_validEyeColors = array('blue', 'brown', 'gray', 'green');
/**
* Valid colors for the hair
* @var array
*/
static private $_validHairColors = array('black', 'blond', 'brown', 'gray',
'red', 'white');
/**
* Valid colors for the skin
* @var array
*/
static private $_validSkinColors = array('black', 'brown', 'red', 'white',
'yellow');
/**
* Color of the eyes
* @var string
*/
protected $_eyeColor = null;
/**
* Color of the hair
* @var string
*/
protected $_hairColor = null;
/**
* Color of the skin
* @var string
*/
protected $_skinColor = null;
/**
* Constructor
*
* @return void
*/
public function __construct()
{}
/**
* Sets the color of the eyes.
*
* @param string $eyeColor Color of the eyes
* @return boolean
*/
public function setEyeColor($eyeColor)
{
if (in_array(strtolower($eyeColor), self::$_validEyeColors)) {
$this->_eyeColor = strtolower($eyeColor);
return true;
} else {
return false;
}
}
/**
* Sets the color of the hair.
*
* @param string $hairColor Color of the hair
* @return boolean
*/
public function setHairColor($hairColor)
{
if (in_array(strtolower($hairColor), self::$_validHairColors)) {
$this->_hairColor = strtolower($hairColor);
return true;
} else {
return false;
}
}
/**
* Sets the color of the skin.
*
* @param string $skinColor Color of the skin
* @return boolean
*/
public function setSkinColor($skinColor)
{
if (in_array(strtolower($skinColor), self::$_validSkinColors)) {
$this->_skinColor = strtolower($skinColor);
return true;
} else {
return false;
}
}
/**
* Returns the color of the eyes.
*
* @return string
*/
public function getEyeColor()
{
return $this->_eyeColor;
}
/**
* Returns the color of the hair.
*
* @return string
*/
public function getHairColor()
{
return $this->_hairColor;
}
/**
* Returns the color of the skin.
*
* @return string
*/
public function getSkinColor()
{
return $this->_skinColor;
}
}

© 2007 Buxaprojects
















