Guidelines

1. PHP

Für PHP-Projekte sollte für die Verwaltung von Paketabhängigkeiten Composer verwendet werden.
Der gesamte Quellcode mit den dazugehörigen assets etc. sollten im Unterverzeichnis src/ liegen!

Tests sollten im Unterverzeichnis tests/ liegen!
Als Testing-Framework sollte entweder PHPUnit (nur Unit-Tests) oder Codeception (auch andere Testarten) verwendet werden.

1.1. Composer Initialisierung

composer init # in einem neuen PHP Projekt

Alle Fragen, die im folgenden nicht mit aufgeführt sind, können auf die default-Einstellungen gelassen werden.

Package name: locr/project-name
Package type: library oder project
License: proprietary
Would you like to define your dependencies (require) interactively [yes]?: no
Would you like to define your dev dependencies (require-dev) interactively [yes]?: no

1.2. PHP_CodeSniffer

PHP_CodeSniffer ist dafür da, um Verletzungen des Coding-Standards zu erkennen und ggf. zu korrigieren.
Zur Installation muss folgendes Kommando ausgeführt werden.

composer require --dev squizlabs/php_codesniffer

Als Basis-Konfiguration sollte folgende ./phpcs.xml verwendet werden.

<?xml version="1.0"?>
<ruleset
    name="locr GmbH Standard"
    xmlns="http://pmd.sf.net/ruleset/1.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="https://pmd.sf.net/ruleset/1.0.0 https://pmd.sf.net/ruleset_xml_schema.xsd"
    xsi:noNamespaceSchemaLocation="https://pmd.sf.net/ruleset_xml_schema.xsd">
    <description>A custom coding standard for locr GmbH projects!</description>
    <arg value="p"/>
    <arg name="extensions" value="php"/>
    <arg name="colors"/>
    <rule ref="PSR2.ControlStructures.SwitchDeclaration"/>
    <rule ref="PSR12"/>
    <rule ref="Squiz.NamingConventions.ValidVariableName.NotCamelCaps"/>
</ruleset>

Um das Testen der Regeln einfacher aufrufen zu können, sollte folgende Zeile in die composer.json Datei eingefügt werden.

{
    "scripts": {
        "dev:lint:phpcs": "phpcs ./src"
    }
}

Jetzt kann man mit:

composer dev:lint:phpcs

die Coding-Standards überprüfen.

VSCode Plugin (PHP Sniffer & Beautifier) installieren mit Strg+P und dann:

ext install ValeryanM.vscode-phpsab

1.3. PHPStan

PHPStan (PHP Static Analysis Tool) ist ein statisches Analyse Tool, um potentielle Fehler im PHP Code zu finden.
Zur Installation muss folgendes Kommando ausgeführt werden.

composer require --dev phpstan/phpstan

Als Basis-Konfiguration sollte folgende ./phpstan.neon.dist verwendet werden.

parameters:
    level: max
    bootstrapFiles:
        - vendor/autoload.php
    paths:
        - src

Darauf aufbauend sollten weitere Konfigurationsdateien für die verschiedenen PHP-Versionen erstellt werden, z.B. phpstan-8.2.neon, phpstan-8.3.neon, …​.
Diese Dateien sollten die phpstan.neon.dist Datei includen und dann die PHP-Version angeben, für die sie gelten sollen.
Die phpstan-8.2.neon könnte z.B. so aussehen:

includes:
	- phpstan.neon.dist

parameters:
    phpVersion: 80200

In einem bestehenden/älteren PHP-Projekt kann man das level erstmal bis auf 1 runtersetzen und nach und nach höher stellen.

Um PHPStan einfacher aufrufen zu können, sollten folgende Zeilen in die composer.json Datei eingefügt werden.

{
    "scripts": {
        "dev:analyze:phpstan": "@phpstan-8.2",
        "dev:analyze:phpstan-8.2": "phpstan --configuration=phpstan-8.2.neon",
        "dev:analyze:phpstan-8.3": "phpstan --configuration=phpstan-8.3.neon",
        "dev:analyze:phpstan-8.4": "phpstan --configuration=phpstan-8.4.neon"
    }
}

Jetzt kann man mit:

composer dev:analyze:phpstan

den Code analysieren lassen.

VSCode Plugin (phpstan) installieren mit Strg+P und dann:

ext install SanderRonde.phpstan-vscode

1.4. PHPUnit

PHPUnit (The PHP Testing Framework) ist für Unit-Tests geeignet.
Zur Installation muss folgendes Kommando ausgeführt werden.

composer require --dev phpunit/phpunit

Als Basis-Konfiguration sollte folgende ./phpunit.xml verwendet werden.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.1/phpunit.xsd"
  bootstrap="vendor/autoload.php"
  executionOrder="depends,defects"
  displayDetailsOnTestsThatTriggerDeprecations="true"
  displayDetailsOnTestsThatTriggerErrors="true"
  displayDetailsOnTestsThatTriggerNotices="true"
  displayDetailsOnTestsThatTriggerWarnings="true"
  cacheDirectory=".phpunit.cache"
  requireCoverageMetadata="true"
  beStrictAboutOutputDuringTests="true"
  beStrictAboutCoverageMetadata="true">
  <testsuites>
    <testsuite name="default">
      <directory>tests</directory>
    </testsuite>
  </testsuites>
  <coverage>
    <report>
      <clover outputFile="test-results/phpunit.clover.xml"/>
      <html outputDirectory="test-results/html"/>
    </report>
  </coverage>
  <source>
    <include>
      <directory suffix=".php">src</directory>
    </include>
  </source>
</phpunit>

Tests sollten unter dem Verzeichnis tests/ abgelegt werden.
Eine einfache ExampleTest.php-Datei könnte wie folgt aussehen:

<?php

declare(strict_types=1);

namespace UnitTests;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;

use Locr\Example;

#[CoversClass(Example::class)]
final class ExampleTest extends TestCase
{
    public function testExample(): void
    {
        $this->assertEquals('OK', Example::getHttpStatusMessage(200));
    }
}

Um PHPUnit einfacher aufrufen zu können, sollte folgende Zeile in die composer.json Datei eingefügt werden.

{
    "scripts": {
        "dev:test:unit": "phpunit"
    }
}

Jetzt kann man mit:

composer dev:test:unit

den Code testen.

1.5. Codeception

Codeception ist ein Testing-Framework mit dem man nicht nur Unit-Tests, sondern auch Integrations-, API-, und Akzeptanz-Tests durchführen kann.

Zur Installation und Einrichtung von Codeception, bitte die Codeception-Seite konsultieren, da das den Rahmen dieser Dokumentation sprengen würde.

1.6. Code-Dokumentation

Dokumenation im Codes selbst sollte möglichst sparsam eingesetzt werden und nur dort, wo es nötig ist, um Unklarheiten oder schwer verständliche Code-Abschnitte zu erklären.

Davon abgesehen, können Methoden von Klassen mit Beispielen dokumentiert werden, um deren Verwendung zu verdeutlichen.
Beispiel:

<?php

declare(strict_types=1);

namespace Locr;

class Example
{
    /**
     * Diese Methode gibt die zu einem Status-Code zugehörige Status-Message zurück. \
     * Falls es den Code nicht gibt, kommt: 'Invalid' zurück.
     *
     * ```php
     * use Locr\Example;
     *
     * $code = 200;
     * $statusMessage = Example::getHttpStatusMessage($code);
     * print "{$code} {$statusMessage}"; // Ausgabe: 200 OK
     * ```
     */
    public static function getHttpStatusMessage(int $code): string
    {
        return match ($code) {
            200 => 'OK',
            400 => 'Bad Request',
            404 => 'Not Found',
            500 => 'Internal Server Error',
            default => 'Invalid'
        };
    }
}

Durch die IntelliSense Funktionen moderner Entwicklungsumgebungen sind diese Dokumentationen für Entwickler leichter zugänglich.