Moderner Build & Development Workflow via Bower, Grunt & Yeoman

Wer die entsprechenden Tools aus der Überschrift noch nicht installiert hat, der sollte zur folgenden Post lesen: -> Toolchain für Webentwickler <-


Modernes Frontend-Development mit Bower, Grunt, Yeoman | IPC13

Slides: https://speakerdeck.com/thorsten/modern-frontend-development

International PHP Conference: Thorsten Rinne (@ThorstenRinne) zeigt die Möglichkeiten von Tools wie Bower, Grunt und Yeoman, mit denen man den kompletten Entwicklungsworkflow im Frontend-Bereich abdecken kann. (auf deutsch)


CSS-Tricks Screencast #124: A Modern Web Designer’s Workflow

Slides: https://speakerdeck.com/chriscoyier/a-modern-web-designers-workflow

CSS-Tricks: Chris Coyier (@Real_CSS_Tricks) Screencast where Chris Coyier explains his workflow.


JavaScript Development Workflow of 2013

Slides: http://dl.dropboxusercontent.com/u/39519/talks/fluent/index.html#/

Fluent 2012: Paul Irish (@paul_irish) Learn what a modern development workflow looks like, from editors and plugins, to authoring abstractions, testing and DVCS integration.


Paul Irish on Web Application Development Workflow

Slides: http://dl.dropboxusercontent.com/u/39519/talks/html5dc-workflow/index.html#1

HTML5DevConf: Paul Irish (@paul_irish) Iterating faster, avoiding bugs through tools, and improved automated testing are great ideas, but in this talk Google’s Paul Irish will show how to really incorporate them into a functional and realistic developer workflow.


… und zum Schluss noch ein Beispiel, wie man mit „Yeoman“ & „Grunt“ & „Bower“ & „AngularJS“ eine modere Web-App baut: http://yeoman.io/codelab.html

Weniger schlecht PHP programmieren

Wir können die Aspekte von guten Code mit folgenden drei Leitlinien zusammenfassen: Lesbarkeit, Erweiterbarkeit, Effizienz. Dabei hängt es ganz von dem Projekt / Projektphase ab, in welcher Reihenfolge diese Leitlinien stehen. In diesem Artikel werde ich mich mit der „Lesbarkeit“ (Syntax, Stil, Standards) von PHP-Code, Kommentaren und git-commits beschäftigen.

Übersicht:
1. Namensgebung
2. Kommentare
3. Code-Standards
4. Refactoring
5. Debug
6. Versionskontrollsystem (git)
7. CI – Server
8. Empfehlung

1.) Namensgebung

Zur Lesbarkeit von Quellcode gehört insbesondere die Benennung von Variablen, Funktionen, Methoden, Klassen, Konstanten usw. Ich versuche dies an ein paar simplen Beispielen zu erklären:

FALSCH RICHTIG Erklärung
str2clean string die lokalen Variablen wurde vereinfacht, so dass man den Quelltext besser lesen kann
margin2Set margin
naviPageEdit_innavi[$value] naviPageEdit[‚inNavi‘][$pageID] ‚value‘ wurde durch ‚pageID‘ ersetzt
naviPageEdit_offline[$value] naviPageEdit[‚offline‘][$pageID] ‚_offine‘ wurde durch eine weitere Array-Stufe ersetzt
startTimerGlobal GLOBALS[’startTimerGlobal‘] die globale Variable ist nun auch als solche erkennbar
dontRewriteFileName = false rewriteFileName = true keine Verneinung in Variablennamen verwenden!!!
pageContentPriorities[$i],
pageContentPriorityArray[$i],
page->contentPriorities[$i]
page->contentPriority[$i] wenn möglich kein Plural für Variablen verwenden ; keine Angabe vom Variablentype im Variablennamen
length,delay length_in_mm,delay_seconds wenn eine bestimmte Information sehr Wichtig für eine Variable ist, dann sollte man diese Information auch mit im Namen aufnehmen

 

Gute Namen beschreiben was der Sinn dieser Variable ist und Funktionen sollten beschreiben was diese tun und nicht wie dies programmiert sind.

FALSCH RICHTIG Erklärung
left_column, right_column navi_column, content_column Der Sinn der Variable ist es, die Navigation oder den Inhalt zu beinhalten.
setHeadlineFontColorToRed() setHeadlineFontColor(‚red‘) Wir beschreiben im Funktionsnamen nicht wie wir die Überschrift hervorheben, sondern dass wir dies überhaupt machen.
renderBackgroundBlack() renderBackgroundColor(‚black‘)

Es folgenden einfache, aussagekräftige Beispiele für Variablennamen: carColor, imageWidth, pageTemplate, daysDateRange, errorCounter, startDateTime, …

 

1.1) Allgemein

Allgemein sollten / dürfen Variablen keine Sonderzeichen (außer dem Unterstrich) enthalten und dürfen in den meisten Programmiersprachen nicht mit Zahlen oder Unterstrich anfangen. Zudem sollte diese in englisch ausgeschrieben werden. Einige Namen sollte man einfach aus seinem Wortschatz streichen: value, key, equals, data, lall, foo, bar, temp, tmp, x, xx, xxx, variable, var, arr, thing, stuff, bla, this, that, something, whatever, dummy, one, two, tree … Wenn man länger über den Namen für z.B. eine Methode nachdenken muss, ist dies ein Indiz dafür, dass man den Zweck dieser Methode noch nicht korrekt durchdacht hat und dass man diese Methode ggf. noch weiter aufteilen kann / sollte.

Beispiel für Wörter, welch man nicht verwenden sollte:

FALSCH RICHTIG Erklärung
foreach ($pages as $key => $value) foreach ($pages as $pageID => $page) Variablen müssen immer Aussagekräftig sein!

Bei Programmen mit Datenspeicherung sieht man im Quelltext häufig folgende Namensgebung: „fetch“, „get“, „retrieve“, „search“, „pull“, „pop“, „read“, usw. um Daten zu erhalten und so etwas wie „put“, „persist“, „set“, „push“, „add“, „insert“, „update“, „write“, usw. um Daten abzuspeichern. Einige Projekte halten sich an der Namensgebung „CRUD“ (Create, Read, Update, Delete) dabei ergibt sich aus dem Zusammenhang, was abgespeichert oder geändert wird, so dass man den entsprechenden Methodennamen auf das wesentliche beschränken und entsprechende Interface definieren kann: z.B.: $user->create(), $car->delete(), $page->update()

Ausnahmen bei gängigen Abkürzungen:

Abkürzung Ausgeschrieben
num numberOf
pos position
len length
max maximum
min minimum
temp || tmp temporary
val value
ret return
fp filePointer

 

1.2) Länge

Man sollte lieber dreimal über einen Namen nachdenken als einmal zu wenig. Und falls einem gerade kein passender Name einfällt, dann sollte man besser einen Aussagekräftigen, wenn auch längeren Namen verwenden. z.B.: cleanFilenameAfterFileupload()

1 Zeichen für Schleifenzähler ist gebräuchlich (z.B.: $i, $x, $y)

1 Wort für Zustands- / Schleifenvariablen (z.B.: $active, $hidden, $flag)

1-3 Wörter für lokale Variablen in Methoden / Funktionen (z.B.: $string, $linkText, $teaserTextType)

1-2 Wörter für Methoden (z.B.: isActive(), isHidden(), isTrue(), send())

1-2 Wörter für Klassen [wenn Namespaces verwendet werden] (Cache, CacheChain, AdaperApc)

1-2 Wörter für Interface [wenn Namespaces verwendet werden] (iCache, iAdapter)

 2-4 Wörter für Globales [sollte man am besten gar nicht verwenden, dazu gleich mehr]

 

1.3) Style

Halte dich an den Code-Style in einem Projekt, auch wenn dieser dir nicht zusagt. Wenn zum Beispiel einmal festgelegt wurde, dass Datenfelder aus der Datenbank in einer Klasse genauso heißen wie das entsprechende Datenbankfeld, dann muss man dies in dem Projekt auch konsequent durchziehen, ansonsten ist das Refactoring wirklich anstrengend. Man sollte sich für alle Projekte in einem Team / Firma auf einen Code-Style festlegen und diesen auch irgendwo niederschreiben (z.B. in einem Wiki), so dass neue Teammitglieder / Mitarbeiter wissen nach welchem Schema man den Quellcode lesen & schreiben sollte.

Es folgt eine kleine Auflistung von Variablen um zu verdeutlichen, welche Möglichkeiten man hat und dass es im Verlauf eines Projektes nicht mehr ganz so einfach ist diese mithilfe von Suchen- / Ersetzen-Tools in Einklang zu bringen:

userName, UserName, USER_NAME, s_userName, user_name, username, name, user->name

Allgemeine-Regel:

Camel Case (Upper Camel Case) für Klassen → z.B.: AdaperApc

Lower Case für namespaces / packages → z.B.: voku\cms\cache

Mixed Case (Lower Camel Case) für Variablen → z.B.: cacheIsReady

Upper Case für Konstanten → z.B.: SECONDS_IN_A_HOUR

– Unterstriche sollten nur für Konstanten verwendet werden

– SQL-Befehle sollten große geschrieben werden → SELECT id, username FROM user

Konsequente Temporäre Variablennamen:

Variable Kontext
$i Schleifenzähler
$j verschachtelte Schleifenzähler
$k weiter verschachtelte Schleifenzähler
$return Rückgabewert
$query SQL-Query String
$result SQL-Query Ergebnis
$fp File-Pointer

 

1.4) Reddick-Namenskonvention

Auch wenn ich dies irgendwann mal in der Schule gelernt habe, solle man Namen nicht mit Tags / Suffixes versehen.

FALSCH RICHTIG Erklärung
gintKundenID $customer->getID() global Integer „KundenID“
$this->mintBenutzerName $this->getName() privat (modular) Integer „BenutzerName“

Zum einen unterstützen uns heute moderne IDEs (z.B.: PhpStorm, Netbeans, Eclipse), so dass man selbst bei schwach typisierten Programmiersprachen wie PHP viele Informationen zu seinen Variablen / Funktionen / Klassen erhält, zum anderen sollte man anstatt eine globale ID für einen Kunden besser eine „Customer“-Klasse anlegen, welche eine Methode mit dem Namen „getID()“ beinhalten könnte.

 

1.5) doppelte Namensvergabe

Klassen: Man sollte vermeiden denselben Namen innerhalb von einer Klasse in unterschiedlichen Zusammenhängen (z.B.: in einer Methode, Konstruktor oder Attribut) zu verwenden, um die Verständlichkeit und Wartbarkeit zu erhöhen.

Methoden / Funktionen: Zudem sollte man nicht dieselbe Variable für verschiedene Zwecke innerhalb einer Funktion verwenden. Man sollte besser eine neue Variable anlegen anstatt eine alte Variabel zu „recyclen“. Ansonsten erschwert dies ebenfalls die Wartbarkeit und Lesbarkeit des Quellcodes.

 

1.6) globale Variablen

Zuerst sollte geklärt werden, was Global heißt. Innerhalb von PHP kann jede Variable welche nicht innerhalb einer Funktion oder Klasse ausgelagert ist „global“ gesetzt / genutzt werden. Benötigt man diese Variablen in einem anderen Kontext (z.B. innerhalb einer Methode) kann man (sollte man jedoch nicht machen) dies mit dem Befehl „global $lall“ zugänglich machen. In den meisten Fällen tut man sich damit jedoch keinen Gefallen, da jemand anderes (oder man selbst) ggf. nicht weiß dass die Variable „$lall“ nun nicht mehr verwendet werden darf, da man diese nun in irgendeiner Methode global setzt hat. Zudem sieht man im Quellcode einer Variable nicht an, dass diese global ist und dass man diese nicht einfach verwenden / verändern darf.

Superglobale Variablen in PHP:

$GLOBALS alle Variablen im globalen Gültigkeitsbereich
$_POST alle Variablen welche via HTTP-POST empfangen wurden
$_GET alle Variabel welche via HTTP-GET empfangen wurden
$_REQUEST alle Variablen welche via HTTP-POST / GET oder via COOKIE empfangen wurden
$_SESSION alle Session-Variablen (wir per User auf den Server gespeichert)
$_COOKIE alle Cookie-Variablen (werden per User auf dem PC des Users gespeichert)
$_FILES alle Datei-Uploads welche via HTTP-POST empfangen wurden
$_SERVER alle Variablen vom Server / Ausführungsumgebung
$_ENV alle Umgebungsvariablen welche z.B. im Betriebssystem gesetzt wurden

 

PHP-Test mit globalen Variablen:

$thisIsGlobal= 1;
echo $GLOBALS['thisIsGlobal'];

$GLOBALS['thisIsGlobal'] = 2;
echo $GLOBALS['thisIsGlobal'];

globalTestNr1();
echo $GLOBALS['thisIsGlobal'];

globalTestNr2();
echo $GLOBALS['thisIsGlobal'];

globalTestNr3($thisIsGlobal);
echo $GLOBALS['thisIsGlobal'];

function globalTestNr1() {
  global $thisIsGlobal;

  $thisIsGlobal= 3;
}

function globalTestNr2() {
  $GLOBALS['thisIsGlobal'] = 4;
}

function globalTestNr3(&$input) {
  $input = 5;
}

// output: 12345

Man sieht bereits bei wenigen Zeilen Code, dass dies nicht zur Wartbarkeit oder Lesbarkeit beiträgt. Zudem habe ich bisher keine Anforderung gesehen, welche man nicht ohne Globale-Variablen lösen könnte: z.B. via Übergabeparameter, Vererbung von Klassen, Singleton-Klassen, ausgelagerte „Konfiguration“ in einer separaten Datei und vieles mehr.

 

2.) Kommentare

Kommentare sollten, wie die bisher erwähnten allgemeine Namensgebung in englisch geschrieben werden, da der Quelltext einerseits länger in Gebrauch sein kann als man denkt, andere (externe) Mitarbeiter daran irgendwann weiterarbeiten und ggf. auch den Weg in andere Projekte findet. Wenn man einmal den Fall hatte, dass man z.B.: eine „SHA-256“ Implementation für ältere PHP-Installationen benötigt und diese Bibliothek nur in Französisch („mais si un char necessite 16bits, on passe tout sur 16 …“ → aha?!) auf „github.com“ zu finden ist, dann weiß man warum man in der Programmierung Konsequent arbeiten sollte / muss.

 

2.1) Was sollte wo Kommentiert werden?

In PHP sollte man zu jeder Methode / Funktion / Klasse einen Kommentar schreiben. Zudem sollte man wichtigen Attributen von Klassen mit einem Kommentar versehen, dabei sollten Mehrzeilige Kommentare vor dem zu beschreibenden Codeabschnitt stehen. Inline-Kommentare sollten nicht das wiedergeben, was man im Quelltext sowieso schon lesen kann, sondern einen Mehrwert bieten. Ein zusätzliches Problem welches entsteht, wenn man in Kommentaren beschreibt, dass der Code exakt macht und nicht was es allgemein machen sollte ist, dass man den Kommentar bei jeder Anpassung des Quellcodes theoretisch auch den Kommentar anpassen müsste, was jedoch nur sehr selten geschieht und somit ist der Kommentar nun ggf. Falsch!!! Mehrzeilige Kommentare sollten einen größeren Code-Abschnitt zusammenfassend beschreiben, dies deutet jedoch wiederum an, dass dieses Code-Abschnitt ggf. auch in eine neue Methode ausgelagert werden kann.

Beispiel:

FALSCH RICHTIG Erklärung
// salutation can be Herr/Frau or 1/2 // set the salutation (ggf. kann man diesen Kommentar auch ganz entfernen)
// get country out of DB depending on PLZ/City // get the country from db Wenn man hier irgendwann auch „Monsieur“ oder „Madame“ übergeben kann, ist dieser Kommentar Fehlerhaft und kann zu echten Problemen führen.
if ($winner) { // JUST GET NEW WINNERS IF A NUMBER IS PASSED // get the new winner from db
if ($winner) {
Der Kommentar sollte immer über einem Codeabschnitt stehen und nicht beschreiben, was sowieso im Code steht.

 

2.2) TODO Kommentar

„TODO“-Kommentare sollten immer mit „TODO“ anfangen und vor dem Nächten Release beseitigt werden. Moderne IDEs zeigen diese Kommentare in einer extra Übersicht / Fenster an, so dass jeder im Projekt weiß, dass hier noch etwas zu tun ist. Es kann zudem sehr hilfreich sein, wenn man Namenskürzel zu den TODOs hinzufügt, so dass man die Zuständigkeit für den Quellcode und für die Lösung des Problems direkt festhält.

2.3) Quellcode Auskommentieren

Quellcode sollte nicht einfach nur auskommentiert werden, wenn dieser nicht mehr benötigt wird, sondern direkt gelöscht werden, da das Versionskontrollsystem sowieso jeder Version des Projektes beinhaltet und der Quellcode somit nicht verloren gehen kann.

2.4) PHPDoc

Moderne IDEs bieten die Möglichkeit Kommentare automatisch zu erstellen, indem man z.B. vor der entsprechenden Funktion „/**“ + [Enter] eingibt. PhpStorm erkennt in vielen Fällen bereits welchen Type die Übergabeparameter und der „Return“-Wert haben, sodass man diese Information nicht in Inline-Kommentaren oder gar in der Variable speichern muss. Zudem kann man z.B. via phpDocumentor eine entsprechende Code-Dokumentation aus diesen Angaben und der Struktur des Projektes erstellen lassen.

Zusätzliche zu den bereits erwähnten PHPDoc (@param, @return) gibt es noch weitere sehr hilfreiche Information welche man zumindest für Klassen / Funktionen / Methoden hinzufügen sollte: @param, @return, @since, @package

Tag

Inhalt

Beschreibung

@abstract Dokumentiert Abstrakte Klasse / Methoden
@access public, private oder protected Beschreibt die Sichtbarkeit von Variablen / Methoden
@author Autor <name@email> Dokumentiert den Autor der z.B.: Klasse
@copyright Name / Datum Dokumentiert Copyright Informationen
@deprecated version Dokumentiert seit wann z.B. eine Funktion als veraltet gilt
@deprec @deprecated
@example /path/to/example Dokumentiert den Pfad zu einem Beispiel
@exception Dokumentiert eine „Exception“ welche von einer Methode geworfen wird → @throws.
@global type $globalvarname Dokumentiert eine globale Variable
@ignore Das Element wird in der Dokumentiert ignoriert
@internal private Information für andere Entwickler
@link URL Eine URL zur eigentlichen Dokumentation
@name global variable name Alias-Name für eine Variablen z.B.: $GLOBALS[‚myvariable‘] → $myvariable
@package Namespaces Dokumentiert den entsprechenden Namespace
@param type [$varname] description Dokumentiert Funktions-Parameter
@return type description Dokumentiert den Rückgabewert, wenn die Funktion einen Rückgabewert beinhaltet, falls dies nicht der Fall ist sollte man diese Angabe in PHP weglassen.
@see element Dokumentiert die Verbindung zu anderen Elementen (global variable, include, page, class, function, define, method, variable).
@since version Dokumentiert seit welcher Version der Software die entsprechende z.B.: Klasse / Methode hinzufügt wurde
@static Dokumentiert statische Klassen oder Methoden
@staticvar type Dokumentiert statische Variablen in einer Funktion oder Klasse
@subpackage Spezifiziert sub-package von Gruppen aus Klassen und Funktionen. | benötigt das Tag @package
@throws Dokumentiert Exceptions von Methoden
@todo Dokumentiert was an dieser Stelle noch gemacht werden muss
@var type Datentype für Klassenattribute
@version Dokumentiert die Version einer Klasse, Funktion

Info: Zudem kann man HTML in PHPDoc schreiben, um z.B. bestimmte <strong>Dinge</strong> hervorzuheben!

Beispiel:

cleanFileName_old
Code ohne PHPDoc
cleanFileName
Code mit PHPDoc

2.5) Zusammenfassung

Besser als jeder Kommentar bleiben jedoch eindeutige Namen und die Aufteilung des Quelltextes in kleine einzelnen Modulen (Klassen + Namespaces), sodass man sich mehr mit dem Programmieren und nicht dem Verstehen des Codes und dem lesen von Kommentaren beschäftigen muss.

Zum Schluss noch ein Link mit vielen Beispielen wie man es nicht machen sollte: ;)

http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered

 

3.) Code-Standards

Man sollte nicht unterschätzen, wie sich die Quellcodeformatierung & Code-Standards auf die Programmierung im Team auswirkt. Einerseits hat jeder seine Vorlieben, andererseits muss man sich auf einen Standard einigen, da man ansonsten z.B. ständig Merge-Konflikte hervorruft und das Refactoring unmöglich gemacht wird. Nachdem man sich auf einen Standard geeinigt hat sollte man die Änderungen der Formatierung automatisch per IDE ausführen lassen. Zudem sollte man die automatische Codeformatierung in einem eigenen „commit“ in das Versionskontrollsystem einchecken. Ich empfehle an dieser Stelle einfach mal bereits bestehende PHP-Standards → PHP Framework Interoperability Group

Tipp: Minimale IDE übergreifende Programmierstandards kann man relativ einfach pro Projekt via „editorconfig.org“ festlegen.

 

3.1) PSR-0 – Autoloader Standard

github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md

– Ein komplett ausgeschriebener Namespace mit Klasse muss die folgende Struktur einhalten \<Anbieter Name>\(<Namespace>\)*<Name der Klasse>

– Jeder Namespace muss den übergeordneten Namespace („Anbieter Namen“) besitzen.

– Jeder Namespace kann beliebig viele Unter-Namespaces besitzen.

– Jeder Trenner („\“) für Namespaces wird beim Laden vom Dateisystem zu einem DIRECTORY_SEPARATOR konvertiert.

– Jedes „_“ Zeichen im KLASSENNAMEN wird zu einem DIRECTORY_SEPARATOR konvertiert. Das Zeichen _ hat keine besondere Bedeutung in einem Namespace.

– Der komplette Namespace wird mit dem Namen der Klasse und dem Suffix .php kombiniert, wenn dieser vom Dateisystem geladen wird.

– Alphabetische Zeichen in Anbieternamen, Namespaces und Klassennamen können in beliebiger Kombination aus Groß- und Kleinschreibung bestehen.

Zusammenfassung:
Jede Klasse muss (seit PHP 5.3) einen eigenen Namespace (mit Angabe des Anbieters) enthalten, so dass man sich sowohl bei Klassennamen also auch bei Namspaces nicht in die Quere kommt.

Beispiele:

Namespace + Klasse Dateipfad
\Doctrine\Common\IsolatedClassLoader /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
\Symfony\Core\Request /path/to/project/lib/vendor/Symfony/Core/Request.php
\Zend\Acl /path/to/project/lib/vendor/Zend/Acl.php
Zend\Mail\Message /path/to/project/lib/vendor/Zend/Mail/Message.php

 

Beispiele: Unterstriche in Namespaces & Klassennamen

Namespace + Klasse Dateipfad
\namespace\package\Class_Name /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

 

Der Standard, welcher hier gesetzt wird, repräsentiert die minimale Anforderung, um eine Kompatibilität hinsichtlich Autoloader zu gewährleisten. Mit der Nutzung der Beispielimplementation des SplClassLoaders [https://gist.github.com/jwage/221634] (verfügbar ab PHP 5.3) kann man somit dynamisch und ohne weiteren Aufwand z.B. externe Bibliotheken nutzen.

 

3.2) PSR-1 – Basic Coding Standard

github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md

– PHP-Dateien dürfen nur <?php und <?= Tags verwenden.

– PHP-Dateien dürfen nur UTF-8 ohne BOM verwenden.

– PHP-Dateien sollten entweder Klassen, Funktionen, Konstanten, etc. enthalten oder diese ausführen. Somit sollten die HTML-Navi z.B. in der Klasse „Navi“ entstehen jedoch nicht von dieser ausgegeben werden. Oder sollte die Klasse „Logger“ zwar die Funktionalität zum Loggen bereitstellen, diese jedoch nicht selber triggern.

– Namensräume und-Klassen müssen PSR-0 folgen.

– Klassennamen müssen in StudlyCaps deklariert werden.

– Klassen Konstanten müssen in Großbuchstaben geschrieben und ggf. mit dem Unterstrich getrennt)

– Methodennamen müssen in camelCase geschrieben werden.

 

3.3) PSR-2 – Coding Style Guide

github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md

– Code muss dem „coding style guide“ PSR [PSR-1] befolgen.

– PHP-Dateien müssen als Zeilenende Unix LF [\n] haben, Windows CRLF [\r\n]

– PHP-Dateien müssen mit einer leeren Zeile enden

– PHP-Dateien haben kein ?> tag am Ende der Datei

– Code muss 4 Leerzeilen pro Einzug verwenden. Tabs werden nicht verwendet.

– Es gibt keine Längenbegrenzung pro Codezeile; jedoch sollten die 120 Zeichen nicht überschritten werden (80 Zeichen oder weniger seien noch besser)

– PHP-Keywörter (z.B.: include, require, use etc.) müssen immer klein geschrieben werden

– PHP-Konstanten (z.B.: true, false, null) müssen ebenfalls klein geschrieben werden

– Es muss eine Leerzeile nach der Deklaration des Namespaces und ebenso nach den Nutzungserklärungen geben.

– Klammern für Klassen & Methoden müssen in der nächsten Zeile, nach dem Klassennamen geöffnet und dürfen erst eine Zeile unter der geöffneten Klammer geschlossen werden.

– Die Sichtbarkeit (public, private, protected) muss zu allen Eigenschaften und Methoden deklariert werden ; „abstract“ und „final“ muss vor der endgültigen Sichtbarkeit deklariert werden ; „static“ muss nach der Sichtbarkeit deklariert werden.

– Kontrollstrukturen (if, elseif, else, switch …) müssen nachfolgend ein Leerzeichen haben (z.B.: if ($lall === true)) ; Methoden und Funktionen benötigen kein extra Leerzeichen (z.B.: echo(‚lall‘);)

– Geöffnete Klammern von Kontrollstrukturen müssen auf der gleichen Linienebene geschlossen werden ; Öffnende und Schließende Klammerpaare dürfen nicht in einer Zeile stehen.

– Geöffnete Klammern von Kontrollstrukturen dürfen nachfolgend keine Leerzeichen besitzen und schließenden Klammern dürfen zuvor keine unnötigen Leerzeichen haben.

Am besten schaut man sich mal ein paar Beispiele auf der angegebenen Webseite an, da ich hier nicht alle Regeln notiert habe. Dies sollte nur eine kleine Übersicht von Überlegungen sein, welche bereits andere Leute für uns übernommen haben, sodass wir und auf wichtigere Dinge wie z.B. dem Implementieren neuer Features konzentrieren können.

 

4.) Refactoring

Vorweg: Ohne moderne IDE mit „Refoctoring“-Funktion (nicht Suchen- & Ersetzten) oder ohne Versionskontrollsystem (z.B. git) sollte man gar nicht mit dem Refactoring anfangen. Zudem sollten für Klassen, welche geändert werden sollen vor und nach den Änderungen entsprechende PHPUnit-Tests durchgeführt bzw. erstellt werden. Es folgt ein etwas längeres Video über das Refactoring via PhpStorm.

5.) Debug

Wie beim Refactoring ist es auch hier sehr Sinnvoll, dass man ein Versionskontrollsystem nutzt, um einerseits zu einem früheren Programmzustand zurückzukehren und andererseits, um seine Änderungen im Nachhinein nachvollziehen zu können.

Bei komplexeren Problemen ist es immer hilfreich, dass Problem im kleinen Nachzustellen. Ggf. kann man die Funktion / Klasse, welche das Problem verursacht außerhalb des gesamten Projektes betrachten und testen.

 

5.1) Fehler-Reporting

Wer einmal an einem größerem Open-Source-Projekt mitgearbeitet hat, wo User Bugs melden, der weiß wie wichtig die Beschreibung von Fehlermeldungen ist. Ich habe dazu extra eine Webseite eingerichtet, nachdem wir viele Meldung bekommen haben, dass etwas nicht funktioniert. → dorimanx.suckup.de/dorimanx-kernel-for-sg2-i9100/howto-report-bugs/

Zusammenfassung:
Minimaler Bug-Report: Was hast du getan (mit welcher Version der Software), was hast du erwartet was passieren sollte und was passiert momentan.

 

5.2) Xdebug

Xdebug ist ein Debugger und Profiler für PHP. Dabei ist der Profiler besonders hilfreich, wenn eine Anwendung Performance Probleme hat, welche man nur schwer lokalisieren kann. Zudem ersetzt Xdebug die eigentlichen Debug-Funktionen von PHP und reichert diese z.B. mit einem Trace des Problems an. Zusätzlich bietet die Erweiterung neue Funktionen z.B.: xdebug_debug_zval(), xdebug_memory_usage(), xdebug_get_function_stack(),

Installation: suckup.de/allgemein/toolchain-fuer-webentwickler

HowTo: code.tutsplus.com/tutorials/xdebug-professional-php-debugging–net-34396

 

5.3) Fehlermeldungen & Logfiles

Gerade bei PHP sollte man die Warnungen während der Programmierung aktivieren und beseitigen, so dass man Programmierfehler bereits bei der Entwicklung sieht und nicht dem Nutzer später auffallen. Ähnlich wie die Ölstand Warnanzeige im Auto sich zu einem wirklichen Problem entwickeln kann, wenn man sich nicht um dessen Behebung kümmert. Außerdem sollte es in jedem PHP-Projekt eine Logging-Klasse (z.B.: monolog, log4php) geben, welche bestimmte definierte Ereignisse aufzeichnet.

 

6.) Versionskontrollsystem (git)

An dieser Stelle möchte ich noch ein paar Worte zu „git“ verlieren. Erstens gibt es bereits viele praktische Programme und Integrationen in allen modernen IDEs, zweitens benötigt man im Standardfall nur wenige einfach Befehle auf der Kommandozeile, um git zu bedienen:

git Task

Notiz

Kommando

Erstellen eines neuen lokalen Repositories
git init
Klone ein existierendes Repository Erstelle eine Kopie eines lokalen Repositories
git clone /path/to/repository
Erstelle eine Kopie eines externen Repositories
git clone username@host:/path/to/repository
Datei hinzufügen Füge eine oder mehrere Dateien zum index
git add <Dateiname|*.php>

git add --all
Einchecken [commit] (wird noch nicht zum Server hochgeladen) Änderungen lokal einchecken
git commit -m "Nachricht"
Neue Dateien (git add) und Änderungen lokal einchecken
git commit -am „Nachricht“
Hochladen [push] von commits Sendet Änderungen zum „master“-Zweig vom Server
git push origin master
Status Zeigt eine Liste von geänderten, neuen und eingecheckten Daten an
git status
Verbindung zu einem externen Server hinzufügen Lokales Repository mit einem Server-Repository verbinden (um anschließend Commit zum Server senen zu können)
git remote add origin <server>
Zeige alle momentan Verbundenen externen Server an
git remote -v

Entwicklungszweig [branche]

Erstelle einen neuen lokalen Entwicklungszweig
git checkout -b <branchname>
Wechseln zwischen lokalen Entwicklungszweigen
git checkout <branchname>
Zeigt alle Entwicklungszweige an
git branch
Löscht ein lokalen Entwicklungszweig
git branch -d <branchname>
Sendet den aktuellen lokalen Entwicklungszweig zum Server
git push origin <branchname>
Sendet alle aktuellen Entwicklungszweige an den Server
git push --all origin
Löscht einen Entwicklungszweig auf dem Server
git push origin :<branchname>
[git push origin --delete <branchname>]
Updates vom externen (Server) Repository Ziehe und vereinige (merge) alle Änderungen vom externen Repository in dein lokales Repository
git pull
Merge einen lokalen Entwicklungszeig in den aktuellen lokalen Entwicklungszeig
git merge <branchname>
Zeige alle Änderungen an:Zeigt alle Änderungen (bis auf Zeilenumbrüche an ; funktioniert auch beim normalen „diff“)Zeigt Unterschiede von verschiedenen Branches an: git diff

git diff -u --ignore-all-space

git diff <sourcebranch> <targetbranch>

Tags Man kann Tags für Release-Versionen der Software vergeben
git tag 1.0.0 <commitID>
CommitId ist eine eindeutige ID zu jedem Commit und kann z.B. folgendermaßen angeigt werden …
git log
Sende alle Tags zum Server
git push --tags origin
lokale Änderungen Rückgängig machen Um eine Datei auf den Stand vom letzten Commit zurück zu drehen:
git checkout -- <filename>
WARNUNG: hier werden auch lokale Commits gelöscht und sowohl die Dateien als auch der Index geändert
git fetch origin

git reset --hard <commitID>
Suchen Sucht im aktuellen Verzeichnis git grep „foo()“

 

6.1) GIT – Commit Message Conventions

Commit-Style Erklärung Beispiel
[+] Ein neues Feature wurde hinzugefügt (auch kleine neue Funktionen oder Tests). [+]: added new SwiftmailerWrapper Class
[-] Feature wurde entfernt z.B. ein „revert“ eines [+] – Commits. [-]: revert some changes from <commitID>
[~] Ein Refactoring Änderung, wobei weder Fehler behebt noch Funktion hinzugefügt wurden [~]: refactored SwiftmailerWrapper Class
[!] Ein Fix für einen Bug. [fixes <issueID>] [!]: fixed embedding images in the SwiftmailerWrapper Class
[!#] Visualisiert, dass eine Änderung ein Sicherheitsproblem behebt. [!#]: fixed send() methode in the SwiftmailerWrapper Class
[!!!] Eine Änderung, welche Grundlegende Änderungen mit sich bringt und sich auch auf die Programmierung anderer Programmierung auswirkt. [!!!]: changed SwiftmailerWrapper constructor-parameter
[*] Alles was nicht zu den bisher definierten Fällen passt, z.B. Code-Style Änderungen, hinzufügen von Dokumentation oder Ändern von Build-Skripten [*]: fixed code-style from the SwiftmailerWrapper Class

 

6.2) GIT – Training

Interaktive Tutorials, welche man einmal in ein paar freien Minuten durchführen sollte.

try.github.io (englisch)

pcottle.github.io/learnGitBranching (deutsch)

 

6.3) git – Server

Wer „git“ im privaten Umfeld einsetzten möchte, seine Projekte jedoch nicht öffentlich auf github.com stellen möchte, der kann z.B. www.gitlab.com/gitlab-com nutzen und für Firmen empfiehlt es sich einen eignen „gitlab“-Server (github.com/gitlabhq/gitlabhq) zu installieren.

 

7.) CI – Server

Wer prüfen möchte, ob man sich in einem Projekt auch an gewisse PHP-Standards hält, der kann z.B. seinen CI-Server (Jenkins) für PHP optimieren und einige Tests automatisch ausführen / auswerten lassen:

– PHP_CodeSniffer → github.com/squizlabs/PHP_CodeSniffer

– PHPUnit → phpunit.de/manual/current/en/index.html

– phpCPD → github.com/EHER/phpunit-all-in-one/tree/master/src/phpcpd

– PHP_Depends → pdepend.org

– phpLOC → github.com/sebastianbergmann/phploc

– phpMD → phpmd.org

– phpdox → phpdox.de

Die entsprechenden Code-Standards kann man anschließend in einer „xml“-Datei (phpcs.xml) im Projekt hinterlegen und auch für andere Projekte verwenden.

JenkinsScreen

8.) Empfehlung

Zum Schluss möchte ich zu diesem Thema noch ein gutes Buch empfehlen → „Weniger schlecht programmieren“ ← . Auch wenn sich das Buch an vielen Stellen direkt an Programmieranfänger richtet, findend man doch einige Beispiele welche man direkt in der täglichen Arbeit umsetzten kann. PS: Am besten kauft man solche Bücher direkt beim Verlag und nicht bei z.B. Amazon. Für dich ist es der selben Preis, der Autor jedoch verdient dabei mehr Geld, da nicht noch ein Händler daran mit verdient.

 

Quellen:

– „Weniger schlecht programmieren“ ISBN: 978-3-89721-567-2 → http://www.oreilly.de/catalog/wenschleprogger/

– PHP: Was ist guter Code? → http://www.sitepoint.com/practical-refactoring-1/

– Lesbaren Quellcode schreiben → http://code.tutsplus.com/tutorials/top-15-best-practices-for-writing-super-readable-code–net-8118

– Test Code Coverage → http://code.tutsplus.com/articles/test-code-coverage-from-myth-to-reality–cms-20442

– PSR? → http://code.tutsplus.com/tutorials/psr-huh–net-29314

– PHP Standards Recommendation → https://github.com/php-fig/fig-standards

– Reddick-Namenskonvention: http://de.wikipedia.org/wiki/Reddick-Namenskonvention#Beispiele

– Refactoring PHP-Code + Beispiel → http://code.tutsplus.com/tutorials/refactoring-legacy-code-part-1-the-golden-master–cms-20331

– Refactoring mit PHPStorm → http://code.tutsplus.com/tutorials/phpstorm-when-the-ide-really-matters–cms-20787

– PHPDocs → http://phpdoc.org/

– PHPDocs – Wiki → http://en.wikipedia.org/wiki/PHPDoc

– Professional PHP Debugging → http://code.tutsplus.com/tutorials/xdebug-professional-php-debugging–net-34396

– xDebug → http://xdebug.org/docs/

– git Befehle → https://confluence.atlassian.com/display/STASH/Basic+Git+commands

– Commit Message rules for TYPO3 Flow → http://docs.typo3.org/flow/TYPO3FlowDocumentation/stable/TheDefinitiveGuide/PartV/CodingGuideLines/PHP.html#commit-messages

– Commit Message Format from AngularJS → https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit

– Template for Jenkins Jobs for PHP Projects → http://jenkins-php.org/installation.html

– HowTo für PHP + Jenkins → http://systemsarchitect.net/continuous-integration-for-php-with-jenkins/

– HowTo (Video) für PHP + Jenkins → https://www.youtube.com/watch?v=PklYO2vYIfc

PHP | TRUE || FALSE

if (-1 == true) {
  echo "aha ...";
}
// output: aha ...

$tmpArray = array(0, 'foo2');
if (in_array("foo", $tmpArray)) {
  echo "aha v2 ...";
}
// output: aha v2 ...

$tmpArray = array(0, 'foo2');
if (in_array("foo", $tmpArray, true)) {
  echo "aha v3 ...";
}
// output:

Das Beispiel mit in Array hab ich auf Twitter gesehen und hat mich im ersten Momentan doch ein wenig verwirrt.

Wenn man den dritten Parameter ($strict = null) von der Funktion „in_array“ nicht auf „true“ setzt, werden die Werte mit dem „==“ Operator verglichen und daher ist ein nicht definierter String == null == 0 -> daher wieder „true“ ;)

Also, sollte man in den meisten Fällen $strict auf „true“ setzten und somit einen Typenvergleich mit dem „===“ Operator durchführen lassen.

<- Übersicht -> 

== true false 1 0 -1 „1“ „0“ „-1“ null array() array(1) array(„php“) „php“ „“ NAN
true true false true false true true false true false false true true true false true
false false true false true false false true false true true false false false true false
1 true false true false false true false false false false false false false false false
0 false true false true false false true false true false false false true true false
-1 true false false false true false false true false false false false false false false
„1“ true false true false false true false false false false false false false false false
„0“ false true false true false false true false false false false false false false false
„-1“ true false false false true false false true false false false false false false false
null false true false true false false false false true true false false false true false
array() false true false false false false false false true true false false false false false
array(1) true false false false false false false false false false true false false false false
array(„php“) true false false false false false false false false false false true false false false
„php“ true false false true false false false false false false false false true false false
„“ false true false true false false false false true false false false false true false
NAN true false false false false false false false false false false false false false false

source: http://habnab.it/php-table.html

UTF-8 & PHP

PHP 5 und frühere Versionen haben keine nativen Unicode-Unterstützung, dass heißt im Ernstfall muss man seine Applikation via „mbstring“-, „iconv-“ und „intl“-Funktionen nachbessern. Daher habe ich eine kleine PHP-Bibliothek zusammengestellt, welche via composer installiert werden kann.

Beispiel:

echo strlen($string) . "\n<br />";
echo UTF8::strlen($string) . "\n<br />";
// output:
// 70
// 67

$string_test1 = strip_tags($string);
$string_test2 = UTF8::strip_tags($string);

echo strlen($string_test1) . "\n<br />";
echo UTF8::strlen($string_test2) . "\n<br />";
// output:
// 53
// 50

Erklärung:
Trotz seines Namens zählt „strlen()“ nicht Zeichen sondern Bytes, bei UTF-8 kann ein Charakter jedoch bis zu vier Bytes [rfc3629] lang sein.

Installation:
https://packagist.org/packages/voku/portable-utf8

Dokumentation:
https://github.com/voku/portable-utf8/master/doc/classes/voku.helper.UTF8.html

Based on Hamid Sarfraz’s work: http://pageconfig.com/attachments/portable-utf8.php

Toolchain für Webentwickler

Vorwort: Ich arbeite in Düsseldorf bei der „menadwork GmbH“ als Webentwickler und vor einigen Monaten habe ich mein Betriebssystem auf Linux (Debian) umgestellt, daher musste ich meine Toolchain / Programmierumgebung neu einrichten. Vorweg kann ich schon mal verraten, dass man sehr gut und effizient damit arbeiten kann. Nur drei, vier Programme (IE, Photoshop, Outlook, MS Office) musste ich per VIrtualBox (Win7) virtualisieren.

Im folgenden wird eine Toolchain / Programmierumgebung für Webprojekte (PHP, HTML, CSS, Sass, JavaScript) eingerichtet. Diese Anleitung werden ich im parallel für Windows und Linux beschreiben.

Übersicht:
1. GIT
2. Webserver + PHP
3. Netbeans / PHPStorm / Sublime Text
4. Composer
5. Ruby && Node.js
6. Bower
7. SASS 
8. Compass
9. auto-prefixer
10. Grunt

1.) git – git-scm.com

Als erstes Installieren / Konfigurieren wir „git“ zur Versionskontrolle und um Quellcode von github.com laden zu können. Auch wenn du mit wenigen Leuten oder alleine an einem Projekt arbeitest ist der Einsatz von „git“ sehr empfehlenswert. Da man so auch noch nach Wochen / Monaten nachvollziehen kann, warum man welche Änderung gemacht hat und diese zudem ganz einfach rückgängig machen kann.

1.1) Installation:

1.1.1) Linux (Debian / Ubuntu)

sudo apt-get install git

 

1.1.2) Windows
http://msysgit.github.io/

Tipp:

– nutze von Anfang an die git-bash!

– bei der Installation wird nach „PATH“ gefragt, hier sollte der zweite Punkt ausgewählt werden, da man ansonsten nur mit der git-bash arbeiten kann

git in der Windows-CMD
git für Windows

– Aktiviere „quick-edit-mode“ in den Einstellungen der git-bash (nach der Installation), so dass man schnell kopieren und einfügen kann

– Windows-Laufwerke (Partitionen) sind direkt unter „/“ aufgehangen -> z.b. cd /d/xampp/

– „vim ~/.vimrc“ -> Konfiguration für „vim

z.B.:

:syntax enable
:set tabstop=2
:set shiftwidth=2
:set expandtab

 

1.2) Konfiguration

1.2.1) „line ending“

Es wird wahrscheinlich zu Probleme (Änderung in jeder Zeile der gespeicherten Datei) bei der Zusammenarbeit von „git unter Windows“ & „git unter Linux (Mac)“ geben, da diese ein anderes „line ending“ haben (\n bzw. \r\n). – http://git-scm.com/book/ch7-1.html#Formatting-and-Whitespace

 

# Windows – Diese wandelt „LF“ (\n) in „CRLF“ (\r\n) Endungen um, wenn der Befehl „git pull“ ausgeführt wird und wandelt dies beim „git commit“ wieder zurück

git config --global core.autocrlf true

 

# Linux (Mac) – Diese wandelt „CRLF“ (\r\n) in „LF“ (\n) Endungen um, wenn der Befehl „git commit“ ausgeführt wird

git config --global core.autocrlf input

-> somit sind die Dateien auf dem Repository (z.B.: github oder gitlab) und in der lokalen git-history immer mit „LF“ (\n) codiert.

 

1.2.2) „push“ 

git config --global push.default simple

-> der Befehl „git push“ schiebt nur commits von der aktuellen „branch“ zum Repository (branch mit dem selben Namen)

 

1.2.3) „user“

Teile „git“ mit wer du bist:

git config --global user.name DEIN_NAME
git config --global user.email DEINE_MAIL@ADRESSE

 

1.2.4) „alias“

Wie in der Linux-Bash (~/.bashrc), kann man auch für git „aliases“ (~/.gitconfig) vergeben:

git config --global alias.last 'log -1 HEAD'
git config --global alias.unstage 'reset HEAD --'
git config --global alias.hard 'reset --hard'
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.cam commit -a -m

 

1.2.5) „color“

git config --global color.diff auto
git config --global color.ui auto
git config --global color.status auto
git config --global color.branch auto

 

2.) Webserver + PHP

Als Webserver installieren wir uns lokal den „Apache“-Webserver, da diese bei vielen Web-Projekten später auch im Live-System zum Einsatz kommt und wir bereits lokal Dinge wie „.htaccess„-Umleitungen etc. testen kann.

2.1) Installation:

2.1.1) Linux (Debian / Ubuntu)

sudo apt-get install apache2 libapache2-mod-php5 php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl php5-apcu php5-xdebug

Achtung: „php5-xdebug“ sollte man nur auf seiner lokalen PC installieren!!!

 

2.1.2) Windows

http://www.apachefriends.org/de/index.html

 

2.2) Konfiguration

Wenn man unter Linux bzw. Mac arbeitet, sollte man den Webserver bzw. PHP so konfigurieren, dass die entsprechenden PHP-Skript-Prozesse mit dem User des Webs laufen. Dies kann man z.B. via suphp oder via php-fpm bewerkstelligen. (Quick & Dirty: die Skripte mit dem eigenen User laufen lassen und das htdocs-Verzeichnis in das eigene Home-Verzeichnis legen)

Unter Windows braucht man sich an dieser Stelle noch keine Gedanken über User-Rechte machen, jedoch spätestens wenn man das Projekte zum ersten mal auf dem Server deployed muss man diesen Schritt auf dem Server wiederholen.

Tipp: hier findet man viele Anleitungen für die Installation von Linux-Servern -> http://www.howtoforge.de/

 

  2.2.1) xDebug -> http://xdebug.org

Unter Windows (XAMPP) ist xDebug bereits vorinstalliert und muss nur noch in der „php.ini“-Datei aktiviert werden. Unter Linux befinden sich die Konfigurationen für PHP-Erweiterungen unter „/etc/php5/config.d/“.

z.B.: für Windows, wenn xampp unter „D:\xampp\“ installiert ist

[XDebug]
;zend_extension = /path/to/xdebug.so
zend_extension = "D:\xampp\php\ext\php_xdebug.dll"
;xdebug.profiler_append = 0
;xdebug.profiler_enable = 1
xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = "D:\xampp\tmp"
xdebug.profiler_output_name = "cachegrind.out.%t-%s"
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "127.0.0.1"
xdebug.trace_output_dir = "D:\xampp\tmp"
xdebug.remote_port=9000

Info: http://wiki.netbeans.org/HowToConfigureXDebug#How_to_configure_XDebug

 

2.3) erster Test mit PHP

php -v

#MYSQL
php -r 'var_dump(function_exists("mysql_query"));'
php -r 'var_dump(function_exists("mysqli_query"));'

#JSON
php -r 'var_dump(function_exists("json_encode"));'

#BCMATH
php -r 'var_dump(function_exists("bcmod"));'

#MAIL
php -r 'var_dump(function_exists("mail"));'

#GD-LIB
php -r 'var_dump(function_exists("imagejpeg"));'

#SESSION
php -r 'var_dump(function_exists("session_start"));'

#SSH
php -r 'var_dump(function_exists("ssh2_connect"));'

#ZIP
php -r 'var_dump(function_exists("zip_open"));'

#GZIP
php -r 'var_dump(function_exists("gzopen"));'

#HASH
php -r 'var_dump(function_exists("hash_hmac"));'

#MCRYPT
php -r 'var_dump(function_exists("mcrypt_module_open"));'

#XML
php -r 'var_dump(function_exists("DomDocument"));'

#CURL
php -r 'var_dump(function_exists("curl_init"));'

#APC
php -r 'var_dump(function_exists("apc_store"));'

 

2.4) PHPUnit installieren

pear config-set auto_discover 1
pear install --alldeps pear.phpunit.de/PHPUnit
pear install --alldeps phpunit/PHPUnit_SkeletonGenerator

 

3.) Netbeans (HTML5 & PHP) || PhpStorm (kostenpflichtig) || Sublime Text

Als nächsten großen Schritt werden wir uns nun eine IDE installieren hier würde ich für größere PHP-Projekte „Netbeans“ bzw. „PhpStorm“ empfehlen, obwohl „Sublime Text“ auch seine Stärken hat und jeder der das Programm noch nicht ausprobiert hat, sollte es einmal testen!!!

3.1) Konfiguration

3.1.1) Netbeans

3.1.1.1) PHPUnit

Unter den Tools -> Options -> PHP -> PHPUnit-> kann man automatisch nach dem bereits installiertem PHPUnit und dem Skeleton-Generator suchen lassen und anschließend aus jeder PHP-Klasse ein PHPUnit-Template erstellen lassen.

php_skeleton php_skeleton_confignetbeans_php_unit_beispiel

3.1.1.2) xDebug

Auch dieses Tool müssen wir einmal konfigurieren unter Tools -> Options -> PHP -> Debugging

netbeans_debug_xdebug netbeans_debug_xdebug_action

Tipp: Wir können unser PHP-Projekt nun nicht nur Debuggen, sondern auch Profilen. Indem wir den Parameter „XDEBUG_PROFILE=1“ per GET oder POST übermitteln und den Output anschließend z.B.: via  KCachegrind visualisieren lassen.

kcachegrind1

 

4.) „composer“ – getcomposer.org

composer ist ein Manager für externe Bibliotheken (libs) und dessen Abhängigkeiten in PHP-Projekten.

4.1) Installation

4.1.1) Linux

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin

 

4.1.2) Windows
https://getcomposer.org/Composer-Setup.exe

 

4.2) Repository -> https://packagist.org/

Auf der Webseite Packagist.org findet man alle Projekte, welche man ohne weitere Anpassungen in seinem Projekt verwenden kann und man kann seine eigenen Projekte einstellen (oder auch eigene Repositories verwenden, falls man diese nicht öffentlich machen will). z.B.: mein Profil -> packagist.org/users/voku/

 

4.3) Konfiguration

Man lege eine Datei mit dem Namen „composer.json“ an und sucht sich seine zu installieren Bibliotheken aus, anschließend ein „composer install –optimize-autoloader“ bzw. „composer update“ und schon kann man die Bibliotheken verwenden (include von „vendor/composer/autoload.php“ nicht vergessen).

 

5.) Ruby && Node.js

Bower ist auch ein Manager für externe Bibliotheken, jedoch auf JavaScript, jQuery, SASS, LESS, CSS etc. (A package manager for the web) ausgerichtet. Für die Installation muss man auch Ruby und Node.js installieren, jedoch benötigen noch andere wichtige Tools in unserer Toolchain diese Programme, daher folgt nun zuerst die kurze Installation unter Linux und die etwas ausführlichere für Windows. :P

 

5.1) Installation

5.1.1) Linux (Debian / Ubuntu)

sudo aptitude install ruby-full build-essential nodejs

 

  5.1.2) Windows

Downlaod & Installation von Ruby & Node.js:

http://rubyinstaller.org/ + „DevKit“
http://nodejs.org/download/

Nachdem wir Ruby Installiert haben müssen wir noch das „DevKit“ für Ruby herunterladen und in das Verzeichnis in welchem du Ruby installiert hat in das Unterverzeichnis „\DevKit“ entpacken. – z.B.: „D:\xampp\Ruby200-x64\DevKit“ und dann folgenden Befehl auf der Kommandozeile (ggf. muss man ruby noch zum PATH hinzufügen oder Windows mal wieder neu-starten)

ruby dk.rb init

Anschließend müssen wir die Datei „dk.rb“ noch wie folgt anpassen:

# This configuration file contains the absolute path locations of all
# installed Rubies to be enhanced to work with the DevKit. This config
# file is generated by the 'ruby dk.rb init' step and may be modified
# before running the 'ruby dk.rb install' step. To include any installed
# Rubies that were not automagically discovered, simply add a line below
# the triple hyphens with the absolute path to the Ruby root directory.
#
# Example:
#
# ---
# - C:/ruby19trunk
# - C:/ruby192dev
#
---
- D:/xampp/Ruby200-x64

… und können die Installation mit folgenden Befehlen abschließen:

ruby dk.rb review
ruby dk.rb install

 

6.) Bower“ – bower.io

Zurück zu Bower, nachdem wir nun Ruby && Node.js installiert haben, können wir nun weiter Tools sehe einfach über die Kommandozeile via npm installieren lassen.

 

6.1) Installation

npm install -g bower

 

6.2) Repository

http://bower.io/search/

 

6.3) Konfiguration

Auch Bower hat eine Konfigurationsdatei „bower.json“, in welcher man die entsprechenden Abhängigkeiten eintragen kann.

Tipp: Video anschauen -> https://egghead.io/lessons/bower-introduction-and-setup

 

7.) „Sass“ – sass-lang.com

Sass ist ein Preprocessor für CSS, so dass man Variablen, Schleifen, Funktionen etc. in CSS nutzten kann. Große Projekte wie z.B.: Bootstrap bieten Ihren Quellcode als scss-Version an. Der Code-Style unterscheidet sich nur minimal von „normalem“ CSS, wobei hier normal in Anführungszeichen stehen, da man die verschiedenen CSS-Selektoren nicht zwingend verschachteln muss. Man kann auch einfach seine bestehende CSS-Datei in eine SCSS-Datei umbenennen und per „sass“ kompilieren oder eine bestehen CSS-Datei (z.B.: test.css) per „sass-convert“ Konvertieren.

sass-convert -F css -T scss css/test.css scss/test.scss

 

7.1) Installation

gem install sass [--pre]

 

 7.2) Links

Basics: http://sass-lang.com/guide

Playground: http://sassmeister.com/

HowTos: http://thesassway.com/

 

7.3) Video

 

 8.) „compass“ – compass-style.org

compass ist ein Framework, welches auf sass aufbaut und dieses um CSS3-Funktionen und z.B. automatisches erstellen und aktualisieren von CSS-Sprites bietet.

 

8.1) Installation

gem install compass [--pre]

Tipp: wenn man noch Browser unterstützen muss, welche keine Transparenzen via CSS (opacity) können, dann sollte man sich mal „compass-rgbapng“ anschauen. Damit werden automatisch Fallback-Bilder (png’s) in der entsprechenden Farbe / Transparenz erstellt und im CSS eingebaut.

 

8.2) Konfiguration

Wir starten indem wir folgende Datei anlegen -> „config.rb“

# Require any additional compass plugins here.
#require "rgbapng"

#add_import_path "vendor/bower/foundation/scss/"
#add_import_path "vendor/bower/normalize-scss/"

# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "css"
sass_dir = "scss"
images_dir = "images"
javascripts_dir = "js"

# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
output_style = :expanded

# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true

# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
line_comments = true

# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass

 

8.3) HowTo

Nachdem wir die Konfiguration angelegt und ggf. angepasst haben, wird mit dem folgendem Befehl automatisch (bei Änderungen) die entsprechende scss-Datei in eine css-Datei kompeliert.

compass watch

compass_watch

 

9.) „auto-prefixer“ – github.com/ai/autoprefixer-rails

Anstatt die entsprechenden CSS3-Funktionen von compass zu verwernden, erscheint es mir einfacher und Sinnvoller entsprechende Vendor-Prefixes automatisch zu erstellen und genau das macht dieses Tool! Man kann es entweder selber aufrufen, in compass oder via „grunt“ (dazu kommen wir gleich) integrieren.

 

9.1) Installation

gem install autoprefixer-rails [--pre]

 

9.2.1) HowTo: Grunt + autoprefixer

(Auch wenn ich noch gar nicht zu grunt geschrieben habe, zeige ich schon mal wie, man dies nutzten kann.)

Als erstes wird das Plugin „grunt-autoprefixer“ installiert und dann folgender Task in der Datei „Gruntfile.js“ angelegt:

    autoprefixer: {
      options: {
        browsers: ['last 4 version']
      },
      multiple_files: {
        expand: true,
        flatten: true,
        src: 'css/*.css',
        dest: 'css/'
      }
    },

 

9.2.2) HowTo: compass + autoprefixer

Folgendes in die compass-Konfiguration „config.rb“ einfügen:

  require 'autoprefixer-rails'

  on_stylesheet_saved do |file|
    css = File.read(file)
    File.open(file, 'w') do |io|
      io << AutoprefixerRails.process(css)
    end
  end

 

10.) „Grunt“ – gruntjs.com

Grunt ist ein Task-Runner, dass heißt das Programme automatisch z.B. nach dem Speichern einer Datei ausgeführt werden können. Falls jemand das Tool noch nicht im Einsatz hat -> einfach mal Testen!!! Erst dieses Tool verknüpft alle hier vorgestellten Tools zu einer „Toolchain“. Und man ist nur noch einen Schritt davon entfernt automatisierte Tests im Browser, Live-Reload im Brower etc. zu nutzen.

 

10.1) Installation

npm install -g grunt-cli
npm install -g grunt-init

 

10.2) HowTo: Init

Entweder man legt sich selber ein entsprechendes „Gruntfile.js“ (Konfiguration) und „package.json“- Datei an oder man nutzt den Befehl:

grunt-init TEMPLATE_NAME

 

10.3) Video

 

Wie im Video erklärt wird, kann man gunt, nachdem man dies einstellt hat, mit dem Befehl „grunt watch“ auf Änderungen von beliebigen Dateien, beliebige Tasks ausführen lasse. In meinem Fall lasse ich z.B. bei Änderungen von „*.scss“-Dateien diese via compass in CSS compilieren, anschließend per „autoprefixer“ überarbeiten, minifizieren und zum Schluss wird automatisch ein reload von dem entsprechendem Brower-Tab durchgeführt. :)

 

10.4) Pluginshttp://gruntjs.com/plugins

Nachdem man ein Plugin in der Datei „package.json“ eingetragen hat, kann man diese über diesen Befehl installieren:

npm install

Tipp: Mit dem Plugin „matchdep“ muss man die entsprechenden Plugins nicht noch in der Datei „Gruntfile.js“ registrieren.

PS: hier noch mein aktuelles Gruntfile + package

 

Viel Spaß beim programmieren!!! :)

Testing PHP-Projekte von github via Travis CI

Um seine PHP-Projekte einfach mit verschiedenen PHP-Versionen zu testen, kann man z.B. „Travis CI“ verwenden, dazu hier ein kleines Beispiel:

 

1.) Projekt bei github.com anlegen 

 

2.) PHP-Unit Test erstellen: z.B.: URLifyTest.php && phpunit.xml && bootstrap.php

 

$ phpunit --bootstrap bootstrap.php  URLifyTest.php
PHPUnit 4.0.4 by Sebastian Bergmann.

.....

Time: 161 ms, Memory: 3.75Mb

OK (5 tests, 23 assertions)

 

3.) Travis-Konfiguration anlegen -> „.travis.yml

 

language: php

php:
  - 5.3
  - 5.4
  - 5.5
  - 5.6

before_script:
  - composer self-update
  - composer install --no-interaction --prefer-source --dev

script:
  - phpunit --coverage-text --verbose

 

4.) Projekt bei Travis CI anlegen (https://travis-ci.org/) und schon beim nächsten „git push“ wird das Projekt automatisch getestet …

 

Travis CI
Travis CI

 

 

Auto-Slideshow via jQuery

Heute stelle ich eine kleine JavaScript-Funktion vor. Das Script ist jedoch nicht für den produktiveren Einsatz bereit, da die 3D-CSS-Transformation via „transform-style: preserve-3d;“ zwar schick aussieht, jedoch noch keine Unterstützung bei allen Browser hat (wie immer ist der IE die Ausnahme).

 

Demo

 

Das ursprüngliche Script „TILTED CONTENT SLIDESHOW“ (Lizenz: MIT | von „Mary Lou„) habe ich hier her. Daraufhin habe ich folgendes ergänzt und das CSS via SASS / Autoprefixer überarbeitet. An dieser Stelle gehe ich jedoch nicht weiter auf das CSS (+ Toolchain) ein, sondern zeige / erkläre die erstellte JavaScript-Funktionalität.

 

  //
  // Im Gegensatz zu anderen Programmiersprachen besitzt JavaScript keine richtigen Klassen, 
  // dafür Objekt-Prototypen und jede Funktion kann als Objekt genutzt werden. 
  //
  // Links:
  // OOP mit JavaScript - Objektliterale: http://www.peterkropff.de/site/javascript/objektliterale.htm
  // Wiedereinführung in JavaScript: https://developer.mozilla.org/de/docs/JavaScript/Eine_Wiedereinfuehrung_in_JavaScript
  // 
  TiltSlider.prototype._autoSlider = function () {

    //
    // Variablen sind in JavaScript meistens global verfügbar, 
    // außer man schreibt "var" vor die Variabel (in einer Funktion) 
    //
    // Links:
    // Variablen-Test: http://jsfiddle.net/voku/mZnh6/1/    
    // JavaScript - Grundlagen - Variablen: http://www.peterkropff.de/site/javascript/variablen.htm
    //
    var wait = 2000;
    var counter = 0;
    //
    // jQuery - Selektoren fungieren meistens wie CSS-Selektoren
    //
    // Links:
    // Crashkurs: jQuery-Selektoren: http://suckup.de/howto/jquery/crashkurs-jquery-selektoren/
    //
    var slideshowNavSpanSelector = $("#slideshow nav span");
    // 
    // Größe vom Array 
    //
    // Links:
    // JS-Array: http://www.w3schools.com/jsref/jsref_obj_array.asp
    //
    var slideshowNavSpanSelectorLength = slideshowNavSpanSelector.length;

    // 
    // Funktion mit Übergabeparameter
    //
    function sliderCheck(counter_tmp) {
      if ($(".navcount" + counter_tmp).hasClass('current')) {
        return true;
      } else {
        return false;
      }
    }
    
    // 
    // Funktion welche die globale "counter"-Variable nutzt
    //
    function autoSlider() {
      if (sliderCheck(counter) === false) {
        $('.navcount' + counter).click();
      }

      if (counter === slideshowNavSpanSelectorLength) {
        counter = 0;
      } else {
        counter++;
      }
    }

    // 
    // Intervall für die "autoSlider"-Funktion
    //
    // Link:
    // http://www.w3schools.com/jsref/met_win_setinterval.asp
    // 
    var timer = setInterval(autoSlider, wait);

    // 
    // Für alle zuvor selektieren "span"-Elemente, wird hier das "MouseEnter"- & "MouseLeave"-Event 
    // von jQuery registriert. Das Event wird im Gegensatz zu "MouseOver" nur ausgelöst, 
    // wenn man in das Element hinein bzw. hinausgeht.
    //
    // Link:
    // https://api.jquery.com/mouseenter/
    //
    slideshowNavSpanSelector.each(function(index) {
      $(this).mouseenter(function() {
        // 
        // Stoppt das zur definierte Intervall
        //
        // Link:
        // http://www.w3schools.com/jsref/met_win_clearinterval.asp
        // 
        clearInterval(timer);

        if (sliderCheck(index) === false) {
          $('.navcount' + index).click();
        }

      }).mouseleave(function () {

        // set counter
        counter = index;

        // ... Intervall wieder starten ...
        timer = setInterval(autoSlider, wait);
      });
    });

  };

 

„CSS -Gradient“ + „Background-Image“ = Problem in Chrome

Falls jemand in der aktuellen Version von Chrome (v32) auch folgenden Fehler hat, kommt hier die Lösung …

 

Problem:

background: url('../images/sprites.png') right -204px no-repeat, linear-gradient(to bottom,#d3d3d3 0%,#ffffff 100%);

 


See the Pen HcjCo by Lars Moelleken (@voku) on CodePen.
1

 

fixed:

background-image: url('../images/sprites.png'), linear-gradient(to bottom, #ffffff 0%,#d3d3d3 100%); 
background-repeat: no-repeat;
background-position: right -204px, 0 0;

 


See the Pen gDGFl by Lars Moelleken (@voku) on CodePen.
1

 

nginx + google-pagespeed

ngx_pagespeed

Google hat „pagespeed“ für nginx veröffentliche, die nginx Äquivalent vom „mod_pagespeed“ für Apache. Dieses Modul kann die Performance von Webseiten optimieren, indem z.B. die zugehörigen Assets (CSS, JavaScript, Bilder) verkleiner bzw. kombiniert werden, um die Ladezeiten zu reduzieren. Dieses Tutorial erklärt wie nginx + pagespeed auf Debian kompiliert/installiert werden kann.

 

Bevor wie starten können müssen wir ggf. einige Pakete nachinstallieren und „deb-src“ in der „/etc/apt/sources.list“ einfügen / auskommentieren.

apt-get update
apt-get install dpkg-dev build-essential zlib1g-dev libpcre3 libpcre3-dev
cd /usr/src/
apt-get source nginx
apt-get build-dep nginx
cd nginx-*/debian/modules/
git clone https://github.com/pagespeed/ngx_pagespeed.git
cd ngx_pagespeed
wget https://dl.google.com/dl/page-speed/psol/1.7.30.1.tar.gz
tar -xzvf 1.7.30.1.tar.gz
cd /usr/src/nginx-*/
vim debian/rules

# und folgende Zeile in der config (config.status.full: config.env.full config.sub config.guess) hinzufügen …

--add-module=$(MODULESDIR)/ngx_pagespeed \

# anschließend können wir uns ein neues „*.dep“-Paket bauen

dpkg-buildpackage -b
dpkg --install ../nginx-full*.dep

# … check …

nginx -V

z.B.:

root@h1687374> nginx -V
nginx version: nginx/1.5.10
TLS SNI support enabled
configure arguments: –prefix=/etc/nginx –conf-path=/etc/nginx/nginx.conf –error-log-path=/var/log/nginx/error.log –http-client-body-temp-path=/var/lib/nginx/body –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –http-log-path=/var/log/nginx/access.log –http-proxy-temp-path=/var/lib/nginx/proxy –http-scgi-temp-path=/var/lib/nginx/scgi –http-uwsgi-temp-path=/var/lib/nginx/uwsgi –lock-path=/var/lock/nginx.lock –pid-path=/var/run/nginx.pid –with-pcre-jit –with-debug –with-http_addition_module –with-http_auth_request_module –with-http_dav_module –with-http_geoip_module –with-http_gzip_static_module –with-http_image_filter_module –with-http_realip_module –with-http_stub_status_module –with-http_ssl_module –with-http_sub_module –with-http_xslt_module –with-http_spdy_module –with-ipv6 –with-mail –with-mail_ssl_module –with-openssl=/usr/src/nginx-1.5.10/debian/openssl-1.0.1f –add-module=/usr/src/nginx-1.5.10/debian/modules/nginx-auth-pam –add-module=/usr/src/nginx-1.5.10/debian/modules/nginx-echo –add-module=/usr/src/nginx-1.5.10/debian/modules/nginx-upstream-fair –add-module=/usr/src/nginx-1.5.10/debian/modules/nginx-dav-ext-module –add-module=/usr/src/nginx-1.5.10/debian/modules/nginx-cache-purge –add-module=/usr/src/nginx-1.5.10/debian/modules/ngx_pagespeed

vim /etc/nginx/nginx.conf

# … und folgende Zeilen über den vHosts einfügen …

pagespeed on;
pagespeed FileCachePath /var/ngx_pagespeed_cache;
mkdir /var/ngx_pagespeed_cache
chown -R www-data:www-data /var/ngx_pagespeed_cache
/etc/init.d/nginx restart
curl -I -p http://localhost | grep X-Page-Speed
apt-get install memcached

# aktiviere memcache  

vim /etc/default/memcached
/etc/init.d/memcached restart

# optional: Fehleranalyse

tail -f /var/log/nginx/error.log  

 

Beispiel-Seite:

http://moelleken.org

 

Beispiel-Konfig:

https://github.com/voku/CONFIG–nginx—php-fpm—mysql

 

Download: (alternativ kann man auch meine bereis kompilierte Version testen)

http://suckup.de/downloads/nginx-full_1.5.10_i386.deb

http://suckup.de/downloads/nginx-common_1.5.10_all.deb

http://suckup.de/downloads/nginx-1.5.10_all.deb

 

Links:

Google-Pagespeed-Doku: https://developers.google.com/speed/pagespeed/module/config_filters

Google_Pagespeed-HowTo: https://developers.google.com/speed/pagespeed/module/build_ngx_pagespeed_from_source

Filter-Übersicht: http://ngxpagespeed.com/ngx_pagespeed_example/