# Zend Framework Programmeer Standaard

## Overzicht

### Bereik

Dit document beschrijft de richtlijnen en hulpmiddelen voor softwareontwikkelaars en teams die programmeren met behulp van of die programmeren op het Zend Framework. De volgende onderwerpen zullen aan de orde komen:

- PHP bestandsformattering

- Benamingsovereenkomst

- Codestijl

- Inline Documentatie

### Doelen

Goede coderichtlijnen zijn belangrijk in alle ontwikkelingsprojecten, in het bijzonder wanneer meerdere programmeurs aan eenzelfde project werken. De coderichtlijnen spelen een grote rol in het produceren van kwaliteitscode met minder bugs en die gemakkelijker kan worden onderhouden.

## PHP Bestandsformattering

### Algemeen

Voor bestanden die alleen PHP code bevatten is de sluitende tag ("?>") nooit toegelaten. Die wordt niet geëist door PHP. Het niet schrijven van deze afbakening voorkomt het toevoegen van spaties in de output.

BELANGRIJK: Toevoegen van binaire gegevens zoals toegelaten door `__HALT_COMPILER()` is niet toegelaten in eender welk Zend Framework PHP bestand of bestanden die daarvan zijn afgeleid. Het gebruik van deze mogelijkheid is alleen toegelaten in speciale installatie scripts.

### Indenting

Gebruik een indent van 4 spaties, zonder tabulatie

### Maximale regellengte

De doellengte voor een regel is 80 tekens, dus ontwikkelaars zouden moeten proberen om zo dicht mogelijk bij de 80 kolommengrens te blijven èn praktisch te blijven. Langere regels zijn aanvaardbaar. De maximale lengte voor eender welke regel code in PHP is 120 tekens.

### Regeleinde

Regeleindes worden geschreven volgens de Unix standaard. Regels moeten eindigen op één enkele linefeed (LF). Een linefeed is een ordinal 10, of een hexadecimale 0x0A.

Gebruik geen carriage returns (CR) zoals Macintosh computers (0x0D).

Gebruik geen carriage return/linefeed combinatie (CRLF) zoals Windows computers (0x0D, 0x0A).

## Benamingsovereenkomst

### Klassen

Het Zend Framework gebruikt een klassebenamingsovereenkomst waarbij de namen van de klassen direct overeenkomen met de mappen waarin ze zijn opgeslagen. De root directory van de Zend Framework is de "Zend" map, waaronder alle klassen hiërarchisch zijn ondergebracht.

Klassenamen mogen alleen alfanumerieke tekens bevatten. Nummers zijn toegelaten in klassename maar worden afgeraden. Underscores zijn alleen toegelaten als vervanging van een padscheider -- de bestandsnaam "Zend/Db/Table.php" moet overeenkomen met de klassenaam "Zend_Db_Table".

Indien een klassenaam bestaat uit meer dan één woord moet de eerste letter van elk woord een hoofdletter zijn. Opeenvolgende hoofdletters zijn niet toegestaan, bv. een klasse "Zend_PDF" is niet toegestaan terwijl "Zend_Pdf" aanvaardbaar is.

Zend Framework klassenamen waarvan Zend of één van de bijdragende partners de auteur is en die met het Framework worden verzonden moeten altijd beginnen met "Zend_" en moeten in de "Zend/" map hiërarchie worden opgeslagen.

Dit zijn voorbeelden van aanvaardbare klassenamen:

    Zend_Db

    Zend_View

    Zend_View_Helper

BELANGRIJK: Code die werkt met het Framework maar er geen deel van is, bv. code geschreven door een Frameworkgebruiker en niet door Zend of één van de Framework partnerbedrijven, mogen nooit beginnen met "Zend_".

### Interfaces

Interface klassen moeten dezelfde overeenkomsten respecteren als andere klassen (zie hierboven), maar moeten bovendien eindigen op het woord "interface", zoals in deze voorbeelden:

    Zend_Log_Adapter_Interface
    Zend_Controller_Dispatcher_Interface

### Bestandsnamen

Voor alle andere bestanden zijn alleen alfanumerieke tekens, underscores en het min teken ("-") toegestaan. Spaties zijn verboden.

Elk bestand dat PHP code bevat moet eindigen op de extensie ".php". Deze voorbeelden tonen aanvaardbare bestandsnamen voor bestanden die klassen bevatten uit de voorbeelden in de vorige sectie:

    Zend/Db.php

    Zend/Controller/Front.php

    Zend/View/Helper/FormRadio.php

Bestandsnamen moeten de overeenkomst met de klassenamen respecteren, zoals hierboven beschreven.

### Functies en methodes

Functienamen mogen alleen alfanumerieke tekens bevatten. Underscores zijn niet toegestaan. Nummers zijn toegestaan in functienamen maar worden afgeraden.

Functienamen moeten altijd met een kleine letter beginnen. Indien een functienaam bestaat uit meer dan één woord, moet de eerste letter van elk nieuw woord een hoofdletter zijn. Dit wordt de "studlyCaps" of "camelCaps" methode genoemd.

Langsprekendheid wordt aangeraden. Functienamen zouden zoveel woorden moeten bevatten als praktisch is om het begrijpen van de code te vergemakkelijken.

Dit zijn voorbeelden van aanvaardbare functienamen:

    filterInput()

    getElementById()

    widgetFactory()

Voor objectgeoriënteerd programmeren zouden databenaderingsmethodes altijd met "get" of "set" moeten worden voorafgegaan. Bij het gebruik van ontwerppatronen, zoals het singleton of factory patroon, zou de naam van de methode de patroonnaam moeten bevatten indien mogelijk. Dit om het gebruik van het patroon gemakkelijker herkenbaar te maken.

Functies in het globale bereik ("drijvende functies") zijn toegestaan maar afgeraden. Het is aanbevolen deze functies in een statische klasse te wikkelen.

### Variabelen

Namen van variabelen mogen alleen bestaan uit alfanumerieke tekens. Underscores zijn niet toegestaan. Nummers zijn toegestaan maar worden afgeraden.

Voor eigenschappen die verklaard worden met het "private" of "protected" concept moet het eerste teken van de functienaam een enkele underscore zijn. Dit is het enige aanvaardbare gebruik van de underscore in een functienaam. Eigenschappen verklaard als "public" mogen nooit met een underscore beginnen.

Zoals functienamen (zie sectie 3.3, hierboven) moeten namen van variabelen altijd met een kleine letter beginnen en volgen ze de "camelCaps" behoofdletteringsovereenkomst.

Langsprekendheid is aangeraden. Variabelen zouden zoveel woorden moeten bevatten als praktisch is. Beknopte variabelnamen zoals "$i" en "$n" worden afgeraden voor alles behalve de kleinst mogelijke loops. Als een loop meer dan 20 coderegels bevat, moeten de index variabelen meer beschrijvende namen hebben.

### Constanten

Namen voor constanten mogen zowel alfanumerieke tekens als de underscore bevatten. Nummers zijn toegelaten in constantnamen.

constantnamen moeten altijd alleen bestaan uit hoofdletters wat de alfanumerieke tekens betreft.

Constanten moeten worden gedefinieerd als klasseleden door het concept "const" te gebruiken. Constanten verklaren in het globale bereik met "define" is toegelaten maar wordt afgeraden.

## Codestijl

### PHP Code Afbakening

PHP code moet altijd worden afgebakend met de volledige standaard PHP markeringen:

    <?php

    ?>

Korte markeringen zijn nooit toegelaten

### Strings

#### String Literals

Wanneer een string letterlijk is (hij bevat geen variabelvervanging), moet altijd de apostroof of "enkele quote" gebruikt worden om de string af te bakenen:

    $a = 'Voorbeeld String';

#### Letterlijke strings die apostrofen bevatten

Wanneer een letterlijke string zelf apostrofen bevat is het toegelaten de string af te bakenen met aanhalingstekens ("double quotes"). Dit is dringend aangeraden voor SQL verklaringen:

    $sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";

De bovenstaande syntax is verkozen boven het "escapen" van de apostrofen.

#### Variabelvervanging

Variabelvervanging is toegestaan met respect voor de volgende vormen:

    $greeting = "Hello $name, welcome back!";

    $greeting = "Hello {$name}, welcome back!";

Om uniformiteit te respecteren is deze vorm niet toegestaan:

    $greeting = "Hello ${name}, welcome back!";

#### String samenvoeging

Strings kunnen samengevoegd worden met de "." operator. Er moet steeds een spatie vòòr en na de "." operator worden ingevoegd om de leesbaarheid te verbeteren:

    $company = 'Zend' . 'Technologies';

Wanneer men strings samenvoegt met de "." operator is het toegelaten de verklaring in meerdere regels op te breken om de leesbaarheid te vergroten. In dat geval moet elke opeenvolgende regel met spaties worden opgevuld zodat de "." operator uitgelijnd is onder de "=" operator:

    $sql = "SELECT `id`, `name` FROM `people` "
         . "WHERE `name` = 'Susan' "
         . "ORDER BY `name` ASC ";

### Arrays

#### Numeriek Geïndexeerde Arrays

Negatieve nummers zijn verboden voor indexen.

Een geïndexeerde array mag starten met eender welk niet negatief nummer. Dit wordt evenwel afgeraden. Het is aangeraden dat alle arrays een basisindex van 0 hebben.

Wanneer men een geïndexeerde array definieert met het `array` concept moet er een spatie worden ingevoegd na elke komma afbakening om de leesbaarheid te verbeteren:

    $sampleArray = array(1, 2, 3, 'Zend', 'Studio');

Het is ook toegelaten om een geïndexeerde array op meerdere regels te definieren. In dat geval moet elke opeenvolgende regel met spaties worden opgevuld zodanig dat het begin van elke regel als volgt is uitgelijnd:

    $sampleArray = array(1, 2, 3, 'Zend', 'Studio',
                         $a, $b, $c,
                         56.44, $d, 500);

#### Associatieve Arrays

Wanneer men associatieve arrays met het `array` concept definieert is het aangeraden de verklaring in meerdere regels op te breken. In dat geval moet elke opeenvolgende regel met spaties worden opgevuld zodat de indexen (keys) en waarden (values) uitgelijnd zijn:

    $sampleArray = array('firstKey'  => 'firstValue',
                         'secondKey' => 'secondValue');

### Klassen

#### Klasse Verklaring

Klassebenaming moet de volgende overeenkomsten volgen.

De accolade wordt steeds op de regel onder de klassenaam geschreven ("one true brace" vorm).

Elke klasse moet een documentatieblok hebben dat de PHPDocumentor standaard volgt.

Code in een klasse moet geïndenteerd zijn met vier spaties.

Eén klasse, éen bestand.

Bijkomende code schrijven in een klassebestand is toegelaten maar wordt afgeraden. Indien men het toch doet moet de bijkomende code met twee lege regels worden gescheiden van de klassecode.

Dit is een voorbeeld van een aanvaardbare klasseverklaring:

    /**
     * Documentatie Blok Hier
     */
    class SampleClass
    {
        // de gehele inhoud van de klasse
        // moet geindenteerd worden met vier spaties
    }

#### Klasse lidvariabelen

Lidvariabelen moeten benaamd worden volgens de variabele benamingsovereenkomst.

Variabelen die in de klasse worden verklaard moeten bovenaan in de klasse worden opgesomd, vòòrdat functies worden verklaard.

Het concept `var` is niet toegestaan. Lidvariabelen moeten steeds hun zichtbaarheid verklaren door één van de `private`, `protected`, of `public` concepten te gebruiken. Toegang verlenen aan lidvariabelen door hen publiek te maken is toegestaan maar wordt afgeraden ten voordele van de databenaderingsmethodes (set/get).

### Functies en Methodes

#### Functie en Methode Verklaring

Functiebenaming moet de benamingsovereenkomsten volgen.

Functies binnen klasses moeten steeds hun zichtbaarheid verklaren door één van de `private`, `protected`, of `public` concepten te gebruiken.

Net zoals klassen, moet de accolade steeds op de regel onder de functienaam worden geschreven ("one true brace" vorm). Er is geen spatie tussen de functienaam en de haakjes voor de argumenten. Er is één spatie tussen de sluitende haakjes en de accolade.

Functies in het globale bereik zijn zeer sterk afgeraden.

Dit is een voorbeeld van een aanvaardbare verklaring van een functie in een klasse:

    /*
     * Documentatie blok hier
     */
    function sampleMethod($a)
    {
        // de gehele inhoud van de functie
        // moet geindenteerd worden met vier spaties
    }

NOTA: Doorgeven per verwijzing (pass by reference) is alleen toegestaan in de functieverklaring:

    function sampleMethod(&$a)
    {}

Call-time pass by reference is verboden.

De terugkeerwaarde mag niet tussen haakjes worden ingesloten. Dat kan de leesbaarheid hinderen en kan ook de code breken indien een methode later wordt veranderd om per verwijzing terug te sturen.

    function foo()
    {
        // FOUT
        return($this->bar);

        // GOED
        return $this->bar;
    }

#### Functie- en Methodegebruik

Functie-argumenten worden gescheiden door één enkele spatie na de komma afbakening. Dit is een voorbeeld van een aanvaardbare functie-aanroep voor een functie die drie argumenten heeft:

    threeArguments(1, 2, 3);

Call-time pass by reference is verboden. Zie de sectie over functieverklaringen voor de juiste wijze om argumenten per verwijzing door te sturen.

Voor functies welke arrays als argument aanvaardden mag de functieaanroep het "array" concept bevatten en kan deze in meerdere regels worden opgesplitst om de leesbaarheid te vergroten. In deze gevallen blijven de regels voor het schrijven van arrays van kracht:

    threeArguments(array(1, 2, 3), 2, 3);

    threeArguments(array(1, 2, 3, 'Zend', 'Studio',
                         $a, $b, $c,
                         56.44, $d, 500), 2, 3);

### Control Statements

#### If / Else / Elseif

Control statements gebaseerd op `if` en `elseif` concepten moeten een enkele spatie voor de openende haakjes van de conditie, en een enkele spatie na de sluitende haakjes.

In de voorwaardeverklaringen tussen de haakjes moeten operators gescheiden worden met spaties om de leesbaarheid te bevorderen. Binnenhaakjes zijn aangeraden voor het groeperen van meer complexe voorwaarden.

De openingsaccolade wordt op dezelfde regel als de voorwaardeverklaring geschreven. De sluitende accolade wordt altijd op een alleenstaande regel geschreven. Alle inhoud binnenin de accolades moet steeds met vier spaties geïndenteerd worden.

    if ($a != 2) {
        $a = 2;
    }

Voor "if" verklaringen die "else if" of "else" inhouden moet de vorm zoals in de volgende voorbeelden zijn:

    if ($a != 2) {
        $a = 2;
    } else {
        $a = 7;
    }

    if ($a != 2) {
        $a = 2;
    } else if ($a == 3) {
        $a = 4;
    } else {
        $a = 7;
    }

PHP laat het toe om in bepaalde gevallen deze verklaringen zonder accolades te schrijven. De codestandaard maakt geen verschil en alle "if", "else if" of "else" verklaringen moeten accolades gebruiken.

Het gebruik van "elseif" is toegestaan maar "else if" wordt sterk aanbevolen.

#### Switch

Control statements geschreven met "switch" moeten een enkele spatie voor de openende haakjes van de voorwaardeverklaring hebben, en een enkele spatie na de sluitende haakjes.

Alle inhoud binnen een "switch" verklaring moet met vier spaties geïndenteerd worden. Inhoud onder elke "case" moet geïndenteerd worden met vier extra spaties.

    switch ($numPeople) {
        case 1:
            break;

        case 2:
            break;

        default:
            break;
    }

`default` mag nooit weggelaten worden van een `switch` verklaring.

NOTA: Het is soms handig een `case` verklaring te hebben die doorvalt naar de volgende `case` verklaring door het weglaten van `break` of `return` in de verklaring. Om deze gevallen van bugs te onderscheiden moet elk van de gevallen waarin een `break` of `return` wordt weggelaten een commentaar "// break intentionally omitted" bevatten.

### Inline Documentatie

#### Documentatie Formaat

Alle documentatieblokken ("docblocks") moeten compatibel zijn met het phpDocumentor formaat. Een beschrijving van het phpDocumentor formaat is buiten het bereik van dit document. Voor meer informatie kunt u terecht op: http://phpdoc.org"

Alle broncodebestanden geschreven voor het Zend Framework of dat ermee samenwerkt moet een "file-level" docblock bevatten aan het begin van elk bestand en een "class-level" docblock onmiddellijk boven elke klasse. Hierna enkele voorbeelden van zulke docblocks.

#### Bestanden

Elk bestand dat PHP code bevat moet een hoofdblok aan het begin van het bestand bevatten dat minstens de volgende phpDocumentor gegevens bevat:

    /**
     * Korte beschrijving van het bestand
     *
     * Lange beschrijving van het bestand (indien aanwzeig)...
     *
     * LICENSE: Licentie informatie
     *
     * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
     * @license    http://www.zend.com/license/3_0.txt   PHP License 3.0
     * @version    $Id:$
     * @link       http://dev.zend.com/package/PackageName
     * @since      File available since Release 1.2.0
    */

#### Klassen

Elke klasse moet een docblock bevatten dat minstens de volgende phpDocumentor gegevens bevat:

    /**
     * Korte beschrijving van de klasse
     *
     * Lange beschrijving van de klasse (indien aanwezig)...
     *
     * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
     * @license    http://www.zend.com/license/3_0.txt   PHP License 3.0
     * @version    Release: @package_version@
     * @link       http://dev.zend.com/package/PackageName
     * @since      Class available since Release 1.2.0
     * @deprecated Class deprecated in Release 2.0.0
     */

#### Functies

Elke functie, methodes inbegrepen, moet een docblock hebben dat minstens het volgende bevat:

- Een beschrijving van de functie

- Alle argumenten

- Alle mogelijke terugwaarden

Het is niet nodig om de "@access" tags te gebruiken want de zichtbaarheid is reeds bekend via het gebruik van "public", "private", of "protected" bij het verklaren van de functie.

Indien een functie of methode een exception mag teruggeven, gebruik @throws:

    @throws exceptionClass [beschrijving]