In diesem Beitrag möchte ich auf PHP_CodeSniffer eingehen und wie man einen eigenen Coding Standard mit selbst definierten Regeln erstellen kann.
== Installation ==
Die Installation bezieht sich auf Ubuntu (UNIX) und kann bei anderen System abweichen. Zur Installation benötigt es eigentlich nur einem Befehl, den wir in unserer Konsole eingeben.
(Voraussetzung ist, dass PEAR auf eurem System schon installiert ist.)
== Anwendung ==
Der PHP_CodeSniffer sollte nun systemweit über den Befehl
aufrufbar sein.
Es werden auch schon einige Coding Standards "out of the box" mitgeliefert. Wenn wir herausfinden wollen, welche Standards das nun sind, nutzen wir einfach folgenden Befehl:
Die Ausgabe sollte in etwa so aussehen:
Wir wollen nun einfach mal eine Beispielklasse gegen den Zend Coding Standard validieren lassen.
Code unserer Beispielklasse:
Alles anzeigen
Jetzt tippen wir in unsere Konsole:
Ausgabe:
Alles anzeigen
== Eigenen Coding Standard ersellen ==
Als erstes müssen wir ins PHP_CodeSniffer Verzeichnis und dort folgende Ordner und Dateien anlegen:
In der ruleset.xml Datei können wir nun festlegen, welche Regeln für unseren Standard verwendet werden:
Alles anzeigen
Im Prinzip haben wir damit festgelegt, dass wir zwei Sniffs für unseren Standard verwenden wollen. Zum einen nutzen wir den "UpperCaseConstantName"-Sniff, der nichts weiter macht, als zu prüfen, ob die Namen der Konstanten groß geschrieben wurden. Zum anderen nutzen wir den "LineLength"-Sniff und legen zusätzlich die Eigenschaften des Sniffs fest bzw. passen sie an. Dabei legen wir fest, dass eine Codezeile maximal 10 Zeichen enthalten darf (die 10 Zeichen sind natürlich nur exemplarisch =).
Im Prinzip haben wir damit einen vollständigen Coding Standard erstellt und können dieses wieder mit dem Befehl überprüfen, der uns die bestehenden Coding Standards anzeigt.
Die Ausgabe sollte in etwa so aussehen:
Nun wollen wir natürlich unseren Standard in Aktion sehen - zuerst legen wir aber noch fest, dass unser Coding Standard als Standard genommen wird, wenn der PHP_CodeSniffer aufgerufen wird:
Ausgabe:
Alles anzeigen
Man kann auch für seinen Standard definieren, dass dieser alle Einstellungen bzw. Sniffs eines anderen Coding Standards als Basis verwendet:
Im obigen Beispiel nehmen wie also den PEAR Coding Standard als Basis und legen fest, dass der "ScopeIntend"-Sniff nicht verwendet wird, dafür aber der Zend "ClosingTag"-Sniff. Die bereits vorhandenen Sniffs können wir uns wie folgt anzeigen lassen:
== Eigenen Sniff erstellen ==
Für unseren neuen Coding Standard wollen wir aber auch eine eigene Regel bzw. einen eigenen Sniff erstellen. Unser Sniff soll einfach nur überprüfen bzw. sicherstellen, dass der öffnende PHP-Tag (<?php) am Anfang der Datei gesetzt ist und nichts davor steht.
Inhalt unseres Sniffs:
Alles anzeigen
Die register()-Methode dient dazu festzulegen, auf welche Tokens wir reagieren wollen. Einen Überblick über die PHP-Tokens gibt es hier: PHP Token-Liste. Wir wollen also reagieren, wenn der "<?php"-Tag gefunden wird. Wenn das der Fall ist, wird die process()-Methode aufgerufen, die noch zwei Argumente übergeben bekommt - mehr dazu unter: PEAR Manual. Da die Variable "$stackPtr" der aktuellen Position des Tokens enthält, können wir damit überprüfen, ob die Position des "<?php"-Tags ungleich der Position 0 ist und geben dann eine Warnung aus, falls dass der Fall sein sollte.
(Anmerkung: Diese Regel ist noch nicht sehr ausgereift, denn was ist, wenn wir nun mehrere öffnende PHP-Tags in unserer Datei nutzen?)
Als nächsten und letztes müssen wir nur noch unsere "ruleset.xml" Datei aktualisieren:
Aktualisierter Inhalt:
Alles anzeigen
Jetzt wird unsere neue Regel in unserem Coding Standard verwendet. Bevor den PHP_CodeSniffer aufrufen, werden wir unsere Beispielklasse anpassen:
Aktualisierter Code unserer Beispielklasse:
Alles anzeigen
Jetzt tippen wir in unsere Konsole:
Ausgabe:
Alles anzeigen
== Installation ==
Die Installation bezieht sich auf Ubuntu (UNIX) und kann bei anderen System abweichen. Zur Installation benötigt es eigentlich nur einem Befehl, den wir in unserer Konsole eingeben.
(Voraussetzung ist, dass PEAR auf eurem System schon installiert ist.)
== Anwendung ==
Der PHP_CodeSniffer sollte nun systemweit über den Befehl
aufrufbar sein.
Es werden auch schon einige Coding Standards "out of the box" mitgeliefert. Wenn wir herausfinden wollen, welche Standards das nun sind, nutzen wir einfach folgenden Befehl:
Die Ausgabe sollte in etwa so aussehen:
Wir wollen nun einfach mal eine Beispielklasse gegen den Zend Coding Standard validieren lassen.
Code unserer Beispielklasse:
Quellcode
Jetzt tippen wir in unsere Konsole:
Ausgabe:
Brainfuck-Quellcode
- FILE: /var/www/exampleClass.php
- --------------------------------------------------------------------------------
- FOUND 8 ERROR(S) AFFECTING 7 LINE(S)
- --------------------------------------------------------------------------------
- 4 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 6 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 6 | ERROR | Private member variable "exampleVar" must contain a leading
- | | underscore
- 8 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 9 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 10 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 11 | ERROR | Spaces must be used to indent lines; tabs are not allowed
- 13 | ERROR | A closing tag is not permitted at the end of a PHP file
- --------------------------------------------------------------------------------
== Eigenen Coding Standard ersellen ==
Als erstes müssen wir ins PHP_CodeSniffer Verzeichnis und dort folgende Ordner und Dateien anlegen:
In der ruleset.xml Datei können wir nun festlegen, welche Regeln für unseren Standard verwendet werden:
Quellcode
- <?xml version="1.0"?>
- <ruleset name="MyPhpCodingStandard">
- <description>MyPhpCodingStandard fuer PHP_CodeSniffer</description>
- <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
- <rule ref="Generic.Files.LineLength">
- <properties>
- <property name="lineLimit" value="10"/>
- <property name="absoluteLineLimit" value="0"/>
- </properties>
- </rule>
- </ruleset>
Im Prinzip haben wir damit festgelegt, dass wir zwei Sniffs für unseren Standard verwenden wollen. Zum einen nutzen wir den "UpperCaseConstantName"-Sniff, der nichts weiter macht, als zu prüfen, ob die Namen der Konstanten groß geschrieben wurden. Zum anderen nutzen wir den "LineLength"-Sniff und legen zusätzlich die Eigenschaften des Sniffs fest bzw. passen sie an. Dabei legen wir fest, dass eine Codezeile maximal 10 Zeichen enthalten darf (die 10 Zeichen sind natürlich nur exemplarisch =).
Im Prinzip haben wir damit einen vollständigen Coding Standard erstellt und können dieses wieder mit dem Befehl überprüfen, der uns die bestehenden Coding Standards anzeigt.
Die Ausgabe sollte in etwa so aussehen:
Nun wollen wir natürlich unseren Standard in Aktion sehen - zuerst legen wir aber noch fest, dass unser Coding Standard als Standard genommen wird, wenn der PHP_CodeSniffer aufgerufen wird:
Ausgabe:
Brainfuck-Quellcode
- FILE: /var/www/exampleClass.php
- --------------------------------------------------------------------------------
- FOUND 1 ERROR(S) AFFECTING 5 LINE(S)
- --------------------------------------------------------------------------------
- 2 | WARNING | Line exceeds 10 characters; contains 20 characters
- 4 | ERROR | Class constants must be uppercase; expected EXAMPLECONSTANT but
- | | found exampleConstant
- 4 | WARNING | Line exceeds 10 characters; contains 28 characters
- 6 | WARNING | Line exceeds 10 characters; contains 26 characters
- 8 | WARNING | Line exceeds 10 characters; contains 32 characters
- 10 | WARNING | Line exceeds 10 characters; contains 28 characters
- --------------------------------------------------------------------------------
Man kann auch für seinen Standard definieren, dass dieser alle Einstellungen bzw. Sniffs eines anderen Coding Standards als Basis verwendet:
Im obigen Beispiel nehmen wie also den PEAR Coding Standard als Basis und legen fest, dass der "ScopeIntend"-Sniff nicht verwendet wird, dafür aber der Zend "ClosingTag"-Sniff. Die bereits vorhandenen Sniffs können wir uns wie folgt anzeigen lassen:
== Eigenen Sniff erstellen ==
Für unseren neuen Coding Standard wollen wir aber auch eine eigene Regel bzw. einen eigenen Sniff erstellen. Unser Sniff soll einfach nur überprüfen bzw. sicherstellen, dass der öffnende PHP-Tag (<?php) am Anfang der Datei gesetzt ist und nichts davor steht.
Inhalt unseres Sniffs:
Quellcode
- <?php
- // Sniff-Klassen müssen immer das PHP_CodeSniffer_Sniff Interface implementieren
- class MyPhpCodingStandard_Sniffs_PHP_PhpOpenTagAtBeginningSniff implements PHP_CodeSniffer_Sniff
- {
- // hier definieren wir, auf welche Tokens wir reagieren wollen
- public function register()
- {
- return array(T_OPEN_TAG);
- }
- // die eigentliche Regel
- public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
- {
- if ($stackPtr != 0)
- {
- $phpcsFile->addWarning('Nothing should precede the PHP open tag.', $stackPtr);
- // wir könnten anstatt einer Warnung auch einen Fehler ausgeben lassen
- // $phpcsFile->addError('Only full PHP opening tags are allowed.', $stackPtr);
- }
- }
- }
- ?>
Die register()-Methode dient dazu festzulegen, auf welche Tokens wir reagieren wollen. Einen Überblick über die PHP-Tokens gibt es hier: PHP Token-Liste. Wir wollen also reagieren, wenn der "<?php"-Tag gefunden wird. Wenn das der Fall ist, wird die process()-Methode aufgerufen, die noch zwei Argumente übergeben bekommt - mehr dazu unter: PEAR Manual. Da die Variable "$stackPtr" der aktuellen Position des Tokens enthält, können wir damit überprüfen, ob die Position des "<?php"-Tags ungleich der Position 0 ist und geben dann eine Warnung aus, falls dass der Fall sein sollte.
(Anmerkung: Diese Regel ist noch nicht sehr ausgereift, denn was ist, wenn wir nun mehrere öffnende PHP-Tags in unserer Datei nutzen?)
Als nächsten und letztes müssen wir nur noch unsere "ruleset.xml" Datei aktualisieren:
Aktualisierter Inhalt:
Quellcode
- <?xml version="1.0"?>
- <ruleset name="MyPhpCodingStandard">
- <description>MyPhpCodingStandard fuer PHP_CodeSniffer</description>
- <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
- <rule ref="MyPhpCodingStandard.PHP.PhpOpenTagAtBeginning"/>
- <rule ref="Generic.Files.LineLength">
- <properties>
- <property name="lineLimit" value="10"/>
- <property name="absoluteLineLimit" value="0"/>
- </properties>
- </rule>
- </ruleset>
Jetzt wird unsere neue Regel in unserem Coding Standard verwendet. Bevor den PHP_CodeSniffer aufrufen, werden wir unsere Beispielklasse anpassen:
Aktualisierter Code unserer Beispielklasse:
Quellcode
Jetzt tippen wir in unsere Konsole:
Ausgabe:
Brainfuck-Quellcode
- FILE: /var/www/exampleClass.php
- --------------------------------------------------------------------------------
- FOUND 1 ERROR(S) AFFECTING 7 LINE(S)
- --------------------------------------------------------------------------------
- 1 | WARNING | Line exceeds 10 characters; contains 23 characters
- 2 | WARNING | Nothing should precede the PHP open tag.
- 2 | WARNING | Nothing should precede the PHP open tag.
- 3 | WARNING | Line exceeds 10 characters; contains 20 characters
- 5 | ERROR | Class constants must be uppercase; expected EXAMPLECONSTANT but
- | | found exampleConstant
- 5 | WARNING | Line exceeds 10 characters; contains 28 characters
- 7 | WARNING | Line exceeds 10 characters; contains 26 characters
- 9 | WARNING | Line exceeds 10 characters; contains 32 characters
- 11 | WARNING | Line exceeds 10 characters; contains 28 characters
- --------------------------------------------------------------------------------
9.390 mal gelesen