Coding-Guidelines aktualisiert
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 („Don’t Repeat Yourself“).
|
- Duplizierten Code vermeiden („Don’t 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user