Coding-Guidelines aktualisiert

blaerf 2025-11-15 11:27:32 +00:00
parent efa37f142c
commit c413077b4e

@ -1,338 +1,338 @@
# PHP Coding Guidelines # PHP Coding Guidelines
Diese Coding-Guidelines gelten für alle PHP-Projekte der Anwendungsentwickler-Klasse. Diese Coding-Guidelines gelten für alle PHP-Projekte der Anwendungsentwickler-Klasse.
Ziel ist ein einheitlicher, gut lesbarer und wartbarer Code-Stil, damit alle im Team effizient zusammenarbeiten können. Ziel ist ein einheitlicher, gut lesbarer und wartbarer Code-Stil, damit alle im Team effizient zusammenarbeiten können.
--- ---
## 1. Allgemeine Grundsätze ## 1. Allgemeine Grundsätze
- Wir verwenden **PHP 8.x**. - Wir verwenden **PHP 8.x**.
- Wir schreiben möglichst **typsicheren Code** (Parameter- und Rückgabetypen). - Wir schreiben möglichst **typsicheren Code** (Parameter- und Rückgabetypen).
- Lesbarkeit steht über Cleverness. - Lesbarkeit steht über Cleverness.
- Duplizierten Code vermeiden („Dont Repeat Yourself“). - Duplizierten Code vermeiden („Dont Repeat Yourself“).
--- ---
## 2. Projektstruktur ## 2. Projektstruktur
Beispielstruktur: Beispielstruktur:
```text ```text
projektname/ projektname/
├─ public/ ├─ public/
├─ src/ ├─ src/
│ ├─ Controller/ │ ├─ Controller/
│ ├─ Model/ │ ├─ Model/
│ ├─ View/ │ ├─ View/
│ └─ Service/ │ └─ Service/
├─ config/ ├─ config/
├─ templates/ ├─ templates/
├─ vendor/ ├─ vendor/
└─ composer.json └─ composer.json
``` ```
Regeln: Regeln:
- Öffentlich zugängliche Dateien nur in `public/`. - Öffentlich zugängliche Dateien nur in `public/`.
- Alle Klassen in `src/`. - Alle Klassen in `src/`.
- Keine Konfigurationswerte hart im Code. - Keine Konfigurationswerte hart im Code.
--- ---
## 3. Dateien & Encoding ## 3. Dateien & Encoding
- `.php` Endung. - `.php` Endung.
- UTF-8 ohne BOM. - UTF-8 ohne BOM.
- Datei beginnt mit `<?php` und ohne schließendes `?>`. - Datei beginnt mit `<?php` und ohne schließendes `?>`.
--- ---
## 4. Namespaces & Autoloading ## 4. Namespaces & Autoloading
- PSR-4 Autoloading. - PSR-4 Autoloading.
- Namespace spiegelt Ordnerstruktur wider. - Namespace spiegelt Ordnerstruktur wider.
Beispiel: Beispiel:
```php ```php
<?php <?php
namespace SchoolApp\User; namespace SchoolApp\User;
class UserService class UserService
{ {
} }
``` ```
--- ---
## 5. Namenskonventionen ## 5. Namenskonventionen
### Klassen ### Klassen
- PascalCase - PascalCase
`UserController`, `InvoiceService` `UserController`, `InvoiceService`
### Interfaces ### Interfaces
- PascalCase + `Interface` - PascalCase + `Interface`
`UserRepositoryInterface` `UserRepositoryInterface`
### Methoden & Funktionen ### Methoden & Funktionen
- camelCase - camelCase
`getUserById()` `getUserById()`
### Variablen / Eigenschaften ### Variablen / Eigenschaften
- camelCase - camelCase
`$userName` `$userName`
### Konstanten ### Konstanten
- UPPER_SNAKE_CASE - UPPER_SNAKE_CASE
`MAX_LOGIN_ATTEMPTS` `MAX_LOGIN_ATTEMPTS`
--- ---
## 6. Formatierung & Einrückung ## 6. Formatierung & Einrückung
- 4 Leerzeichen. - 4 Leerzeichen.
- Zeilenlänge max. 120 Zeichen. - Zeilenlänge max. 120 Zeichen.
- Öffnende Klammer in derselben Zeile. - Öffnende Klammer in derselben Zeile.
Beispiel: Beispiel:
```php ```php
if ($condition) { if ($condition) {
// ... // ...
} else { } else {
// ... // ...
} }
``` ```
--- ---
## 7. Typen & strikte Typisierung ## 7. Typen & strikte Typisierung
- Am Anfang der Datei: - Am Anfang der Datei:
```php ```php
declare(strict_types=1); declare(strict_types=1);
``` ```
- Parameter- und Rückgabetypen nutzen. - Parameter- und Rückgabetypen nutzen.
Beispiel: Beispiel:
```php ```php
public function findUserById(int $id): ?User public function findUserById(int $id): ?User
{ {
} }
``` ```
- Nullable Typen: - Nullable Typen:
```php ```php
?string ?string
``` ```
--- ---
## 8. Arrays & Strings ## 8. Arrays & Strings
### Arrays ### Arrays
Kurzsyntax: Kurzsyntax:
```php ```php
$items = [ $items = [
'apple', 'apple',
'banana', 'banana',
]; ];
``` ```
### Strings ### Strings
- `'...'` ohne Variablen - `'...'` ohne Variablen
- `"..."` mit Variablen - `"..."` mit Variablen
--- ---
## 9. Objektorientierung ## 9. Objektorientierung
### Sichtbarkeit ### Sichtbarkeit
- Standard: `private` - Standard: `private`
- Nur wenn nötig `protected` oder `public`. - Nur wenn nötig `protected` oder `public`.
Beispiel: Beispiel:
```php ```php
class User class User
{ {
private string $name; private string $name;
public function getName(): string public function getName(): string
{ {
return $this->name; return $this->name;
} }
} }
``` ```
### Konstruktor-Injection ### Konstruktor-Injection
```php ```php
public function __construct( public function __construct(
private InvoiceRepositoryInterface $repo private InvoiceRepositoryInterface $repo
) {} ) {}
``` ```
--- ---
## 10. Fehlerbehandlung & Exceptions ## 10. Fehlerbehandlung & Exceptions
- Keine `die()`, `exit()`, `var_dump()` im Produktivcode. - Keine `die()`, `exit()`, `var_dump()` im Produktivcode.
- Exceptions statt Abbrüche. - Exceptions statt Abbrüche.
Beispiel: Beispiel:
```php ```php
throw new UserNotFoundException("User not found"); throw new UserNotFoundException("User not found");
``` ```
--- ---
## 11. Kommentare & PHPDoc ## 11. Kommentare & PHPDoc
- Kommentare erklären *warum*, nicht *was*. - Kommentare erklären *warum*, nicht *was*.
Schlecht: Schlecht:
```php ```php
// increment i // increment i
$i = $i + 1; $i = $i + 1;
``` ```
### PHPDoc ### PHPDoc
```php ```php
/** /**
* Berechnet die Gesamtsumme einer Rechnung. * Berechnet die Gesamtsumme einer Rechnung.
*/ */
public function calculateTotal(Invoice $invoice): float public function calculateTotal(Invoice $invoice): float
{ {
} }
``` ```
--- ---
## 12. Sicherheit ## 12. Sicherheit
### Eingaben validieren ### Eingaben validieren
```php ```php
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
``` ```
### SQL Injection vermeiden ### SQL Injection vermeiden
```php ```php
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email'); $stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $email]); $stmt->execute(['email' => $email]);
``` ```
### XSS verhindern ### XSS verhindern
```php ```php
<?= htmlspecialchars($userName, ENT_QUOTES, 'UTF-8') ?> <?= htmlspecialchars($userName, ENT_QUOTES, 'UTF-8') ?>
``` ```
### Passwörter ### Passwörter
```php ```php
password_hash($pw, PASSWORD_DEFAULT); password_hash($pw, PASSWORD_DEFAULT);
password_verify($pw, $hash); password_verify($pw, $hash);
``` ```
### CSRF-Token ### CSRF-Token
```html ```html
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>"> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
``` ```
--- ---
## 13. Git-Workflow ## 13. Git-Workflow
- Häufige, kleine Commits. - Häufige, kleine Commits.
- Commit-Messages im Imperativ: - Commit-Messages im Imperativ:
- `Add login form` - `Add login form`
- `Fix session timeout` - `Fix session timeout`
- Keine sensiblen Daten committen. - Keine sensiblen Daten committen.
- `.gitignore` für: - `.gitignore` für:
- `vendor/` - `vendor/`
- `.idea/` - `.idea/`
- `.vscode/` - `.vscode/`
- `logs/` - `logs/`
- `cache/` - `cache/`
--- ---
## 14. Code-Review-Regeln ## 14. Code-Review-Regeln
- Review vor jedem Merge. - Review vor jedem Merge.
- Kritik ist sachlich. - Kritik ist sachlich.
- Reviewer geben konkrete Vorschläge. - Reviewer geben konkrete Vorschläge.
--- ---
## 15. Beispiel-Code ## 15. Beispiel-Code
```php ```php
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace SchoolApp\User; namespace SchoolApp\User;
use PDO; use PDO;
class UserRepository implements UserRepositoryInterface class UserRepository implements UserRepositoryInterface
{ {
public function __construct(private PDO $connection) public function __construct(private PDO $connection)
{ {
} }
public function findByEmail(string $email): ?User public function findByEmail(string $email): ?User
{ {
$sql = 'SELECT id, name, email FROM users WHERE email = :email'; $sql = 'SELECT id, name, email FROM users WHERE email = :email';
$stmt = $this->connection->prepare($sql); $stmt = $this->connection->prepare($sql);
$stmt->execute(['email' => $email]); $stmt->execute(['email' => $email]);
$data = $stmt->fetch(PDO::FETCH_ASSOC); $data = $stmt->fetch(PDO::FETCH_ASSOC);
if ($data === false) { if ($data === false) {
return null; return null;
} }
return new User( return new User(
(int) $data['id'], (int) $data['id'],
(string) $data['name'], (string) $data['name'],
(string) $data['email'] (string) $data['email']
); );
} }
} }
``` ```
--- ---
## 16. Weiterentwicklung ## 16. Weiterentwicklung
- Guidelines sind lebendig. - Guidelines sind lebendig.
- Änderungen im Team besprechen. - Änderungen im Team besprechen.
- Aktualisierungen per Pull-Request. - Aktualisierungen per Pull-Request.
--- ---