Philosophie
Das DotApp PHP Framework ist von Grund auf modular aufgebaut. DotApp bietet eine robuste und skalierbare Grundlage für moderne Webanwendungen und stellt eine modulare Architektur in den Mittelpunkt, um Flexibilität, Wartbarkeit und Effizienz zu gewährleisten.
Warum ein modularer Entwurf?
Modularität ist das Herzstück der DotApp-Philosophie. Indem Anwendungen als Sammlung unabhängiger, wiederverwendbarer Module strukturiert werden, ermöglicht DotApp Entwicklern:
- skalierbare Anwendungen mit klarer Trennung der Zuständigkeiten zu bauen.
- Komponenten projektübergreifend wiederzuverwenden und so die Entwicklungszeit zu verkürzen.
- einzelne Teile einer Anwendung zu warten und zu aktualisieren, ohne das Gesamtsystem zu beeinträchtigen.
- neue Funktionen oder Drittanbieter-Werkzeuge nahtlos zu integrieren.
Dieser Ansatz hält Ihre Projekte übersichtlich und anpassungsfähig – ob Sie einen kleinen Prototyp oder eine große Unternehmensanwendung bauen.
Robuste Grundlage, empfohlene Praktiken
DotApp liefert eine solide Grundlage mit Werkzeugen und Konventionen für die modulare Entwicklung. In dieser Anleitung konzentrieren wir uns auf die empfohlenen Praktiken, die zu den Designzielen von DotApp passen:
- Modulzentrierter Workflow: Organisieren Sie Ihre Anwendung in in sich abgeschlossenen Modulen für Klarheit und Skalierbarkeit.
- Einheitliche Struktur: Folgen Sie den DotApp-Konventionen für Controller, Templates und Konfigurationen, um die Zusammenarbeit zu erleichtern.
- Bewährte Praktiken: Nutzen Sie die integrierten Werkzeuge für Routing, Templates und Modulverwaltung, um typische Fallstricke zu vermeiden.
- Zukunftssicherheit: Bauen Sie modular, damit spätere Erweiterungen oder Refactorings mühelos bleiben.
DotApp ist flexibel genug für alternative Ansätze; diese Anleitung betont jedoch die Methoden, die die modulare Architektur am besten nutzen. Ziel ist es, Techniken zu vermitteln, die die Stärken des Frameworks ausschöpfen und ineffiziente oder fehleranfällige Muster vermeiden.
Wie geht es weiter?
Bereit, mit DotApp zu entwickeln? Wechseln Sie zum Abschnitt Installation, um das Framework einzurichten und Ihre modulare Reise zu beginnen. Für einen tieferen Einstieg in Ihr erstes Modul siehe den Abschnitt Erstes Modul und Einrichtung.
Mit Stolz hergestellt in der Slowakei 🇸🇰
Installation
Die Installation des DotApp PHP Framework ist schnell und flexibel. Wählen Sie eine der drei folgenden Methoden, um Ihr Projekt einzurichten. Jede Methode führt zur gleichen modularen Projektstruktur, die für die Entwicklung bereit ist.
Option 1: Git-Klon
Wenn Git installiert ist, können Sie das DotApp-Repository direkt klonen. Führen Sie im Terminal den folgenden Befehl aus:
git clone https://github.com/dotsystems-sk/dotapp.git ./
Damit entsteht ein DotApp-Projekt im aktuellen Verzeichnis. Kein Git? Kein Problem — nutzen Sie eine der anderen Methoden.
Option 2: DotApper CLI
Laden Sie das CLI-Werkzeug dotapper.php herunter und verwenden Sie es zur Installation von DotApp. Gehen Sie so vor:
- Laden Sie die Datei herunter: dotapper.php.
- Speichern Sie sie in Ihr Projektverzeichnis.
- Führen Sie den Installationsbefehl aus:
php dotapper.php --install
Damit wird DotApp mit allen erforderlichen Abhängigkeiten eingerichtet.
Option 3: ZIP-Download
Bevorzugen Sie einen manuellen Weg? Laden Sie die DotApp-ZIP-Datei herunter und entpacken Sie sie:
- ZIP herunterladen: DotApp main.zip.
- Entpacken Sie den Inhalt in Ihr Projektverzeichnis.
Nach dem Entpacken ist Ihr Projekt einsatzbereit.
Projektstruktur
Nach der Installation hat Ihr Projektverzeichnis die folgende modulare Struktur:
project-root/
├── index.php
├── dotapper.php
├── app/
│ ├── config.php
│ ├── modules/ # your application logic
│ │ └── HelloWorld/
│ │ ├── module.init.php
│ │ ├── module.listeners.php
│ │ ├── Controllers/
│ │ ├── Middleware/
│ │ ├── Models/
│ │ ├── views/
│ │ └── assets/
│ ├── parts/ # framework core — do not edit
│ ├── runtime/
│ └── vendor/
└── assets/
├── dotapp/
└── modules/
Anwendungs-Controller, Middleware, Modelle und Views gehören nach app/modules/{ModuleName}/. app/parts/ ist der Framework-Kern. Routen werden in der jeweiligen module.init.php des Moduls deklariert.
Wie geht es weiter?
Mit installiertem DotApp können Sie Ihr erstes Modul erstellen. Wechseln Sie zum Abschnitt Erstes Modul und Einrichtung, um Ihre modulare Anwendung zu bauen.
Erstes Modul und Einrichtung
Mit installiertem DotApp PHP Framework können Sie Ihr erstes Modul erstellen. Module sind der Kern der modularen Architektur von DotApp und erlauben es, die Anwendung in wiederverwendbare, in sich abgeschlossene Komponenten zu gliedern. In diesem Abschnitt erstellen wir ein Modul HelloWorld und konfigurieren es so, dass es /helloworld bedient.
Das Modul erstellen
Erzeugen Sie ein neues Modul mit der DotApper CLI. Führen Sie im Projektverzeichnis den folgenden Befehl aus:
php dotapper.php --create-module=HelloWorld
Sie sehen die Ausgabe:
Module successfully created in: ./app/modules/HelloWorld
Damit entsteht ein neues Modul HelloWorld im Verzeichnis app/modules.
Modulstruktur
Das Modul HelloWorld hat die folgende Struktur:
├───modules
│ │ .gitkeep
│ │
│ └───HelloWorld
│ │ module.init.php
│ │ module.listeners.php
│ │
│ ├───Api
│ │ Api.php
│ │
│ ├───assets
│ │ howtouse.txt
│ │
│ ├───Controllers
│ │ Controller.php
│ │
│ ├───Libraries
│ ├───Middleware
│ ├───Models
│ ├───translations
│ └───views
│ │ clean.view.php
│ │
│ └───layouts
│ example.layout.php
Wofür die einzelnen Dateien und Verzeichnisse dienen:
module.init.php: Definiert die Routen des Moduls und die Initialisierungsbedingungen und steuert, wann und wie das Modul geladen wird.module.listeners.php: Registriert Event-Listener für das Modul, damit es auf Framework-Ereignisse wie das Laden von Modulen reagieren kann.Api/Api.php: Ein Beispiel-API-Controller für API-Endpunkte (kann gelöscht oder ignoriert werden).assets/: Speichert modulspezifische Assets wie CSS, JavaScript oder Bilder. Enthält eine Anleitunghowtouse.txtfür Einsteiger.Controllers/Controller.php: Ein Beispiel-Controller (kann gelöscht oder ignoriert werden).Libraries/: Enthält eigene PHP-Bibliotheken oder Klassen, die zum Modul gehören.Middleware/: Enthält Middleware-Klassen für die Anfrageverarbeitung, etwa Authentifizierung oder Validierung.Models/: Speichert Modellklassen für Datenbankzugriffe oder Geschäftslogik.translations/: Verwaltet Sprachdateien für die Internationalisierung.views/: Enthält View-Templates, darunterclean.view.php(eine Beispiel-View) undlayouts/example.layout.php(ein Beispiel-Layout); beide können gelöscht oder ignoriert werden.
Die Beispieldateien (Api.php, Controller.php, clean.view.php, example.layout.php) sind als Einstiegshilfe enthalten. In dieser Anleitung erstellen wir eigene Controller und Views, daher können Sie diese Dateien gefahrlos löschen oder ignorieren.
Das Modul konfigurieren
Konfigurieren Sie das Modul HelloWorld so, dass es /helloworld bedient.
Schritt 1: Event-Listener
Die erzeugte Datei app/modules/HelloWorld/module.listeners.php ist der Ort für Modulereignisse. Routen gehören in initialize() (nächste Schritte). Lassen Sie register() leer, sofern Sie keine Ereignisse abonnieren.
DotApp löst mehrere modulspezifische Ereignisse aus, falls Sie sie später benötigen:
dotapp.module.HelloWorld.init.start: Wird ausgelöst, wenn die Modulinitialisierung beginnt.dotapp.module.HelloWorld.init.loading: Wird ausgelöst, wenn die Hauptfunktionen des Moduls (z. B. Routen) geladen werden, sofern die Initialisierungsbedingungen erfüllt sind.dotapp.module.HelloWorld.init.loaded: Wird ausgelöst, nachdem die Routen und Funktionen des Moduls geladen wurden.dotapp.module.HelloWorld.init.end: Wird ausgelöst, wenn die Modulinitialisierung endet, unabhängig davon, ob die Bedingungen erfüllt waren.dotapp.modules.loaded: Wird ausgelöst, nachdem alle Module geladen wurden.
Schritt 2: Modulinitialisierung konfigurieren
Öffnen Sie app/modules/HelloWorld/module.init.php, um festzulegen, wann das Modul aktiv werden soll. Passen Sie die Funktion initializeRoutes so an, dass das Modul für Routen aktiviert wird, die mit /helloworld beginnen:
public function initializeRoutes() {
return ['/helloworld', '/helloworld/*'];
}
So wird das Modul nur für URLs aktiv, die mit /helloworld beginnen (z. B. /helloworld, /helloworld/, /helloworld/sekcia). ['*'] (Aktivierung für alle URLs) ist weniger effizient und für große Projekte nicht empfohlen; daher beschränken wir uns auf unser Routenpräfix.
Konfigurieren Sie anschließend die Funktion initializeCondition, um anhand der Routenübereinstimmung zu entscheiden, ob das Modul initialisiert werden soll. Setzen Sie sie standardmäßig auf:
public function initializeCondition($routeMatch) {
return $routeMatch;
}
Damit wird das Modul aktiviert, sobald eine Route aus initializeRoutes passt. Sie können eigene Logik hinzufügen. Beispielsweise nur in einem bestimmten Jahr:
public function initializeCondition($routeMatch) {
if ($routeMatch === true) {
if (date("Y") == 2026) return true;
}
return false;
}
Dieses Beispiel dient nur der Veranschaulichung. Für diese Anleitung behalten Sie return $routeMatch; bei.
Schritt 3: Erste Routen definieren
Importieren Sie in derselben Datei module.init.php oben Config und Router und definieren Sie die Routen in initialize:
public function initialize($dotApp) {
Config::module('HelloWorld', 'prefix') ?? Config::module('HelloWorld', 'prefix', '/helloworld');
$p = rtrim((string) Config::module('HelloWorld', 'prefix'), '/');
Router::get($p, 'HelloWorld:Home@index!', Router::STATIC_ROUTE);
Router::get($p . '/', 'HelloWorld:Home@index!', Router::STATIC_ROUTE);
}
Damit werden statische Routen für /helloworld und /helloworld/ eingerichtet, die auf die Methode index des Controllers Home im Modul HelloWorld zeigen. Router::STATIC_ROUTE entspricht dem exakten Pfad.
Wie geht es weiter?
Ihr Modul HelloWorld ist erstellt und konfiguriert. Als Nächstes erstellen wir den Controller Home, der die Route /helloworld verarbeitet. Wechseln Sie zum Abschnitt Erster Controller, um fortzufahren.
Erster Controller
Mit konfiguriertem Modul HelloWorld erstellen Sie einen Controller für die Route /helloworld. Controller liegen in app/modules/{Module}/Controllers/. Diese Anleitung verwendet Home, denselben Controller wie die Live-Demo.
Den Controller erstellen
Erzeugen Sie den Controller Home mit der DotApper CLI:
php dotapper.php --module=HelloWorld --create-controller=Home
Sie sehen:
Controller 'Home' successfully created!
Damit entsteht app/modules/HelloWorld/Controllers/Home.php.
Den Controller einrichten
Öffnen Sie diese Datei und implementieren Sie index als Methode public static. Die Live-Demo rendert eine View mit der Fassade Renderer. setView() muss vor setViewVar() laufen. Fehlt die View, gibt renderView() eine leere Zeichenkette zurück.
namespace Dotsystems\App\Modules\HelloWorld\Controllers;
use Dotsystems\App\Parts\Logger;
use Dotsystems\App\Parts\Renderer;
use Dotsystems\App\Parts\Response;
class Home extends \Dotsystems\App\Parts\Controller
{
public static function index($request)
{
$html = Renderer::new()
->module('HelloWorld')
->setView('hello')
->setViewVar('title', 'Hello World')
->setViewVar('message', 'DotApp 2.0 is running.')
->renderView();
if ($html === '') {
Logger::use()->error('HelloWorld view produced empty output');
return new Response(500, 'Template error');
}
return $html;
}
}
Erstellen Sie app/modules/HelloWorld/views/hello.view.php als vollständige HTML-Seite (die Live-Demo verwendet für diesen Bildschirm kein verschachteltes Layout):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ var: $title }}</title>
<link rel="stylesheet" href="/assets/modules/HelloWorld/css/hello.css" />
</head>
<body>
<main>
<h1>{{ var: $title }}</h1>
<p>{{ var: $message }}</p>
<p><a href="/documentation/step-by-step">Back to the guide</a></p>
</main>
</body>
</html>
Die Routenzeichenkette lautet 'HelloWorld:Home@index!'. Das abschließende ! deaktiviert die Dependency Injection für diese Methode. Das erste Argument ist immer $request.
Wie geht es weiter?
Wechseln Sie zum Abschnitt Hello World, um die Seite im Browser zu öffnen.
Hello World
Ihr Modul HelloWorld und der Controller Home sind bereit. Dieser Abschnitt bestätigt, dass /helloworld gerendert wird.
Ihre Anwendung testen
Verwenden Sie den integrierten PHP-Server aus dem Projektstamm:
php -S 127.0.0.1:8000
Öffnen Sie anschließend http://127.0.0.1:8000/helloworld (oder /helloworld/). Sie sollten die Überschrift Hello World und die Nachricht aus der View sehen.
Die Hello-World-Seite ansehen
Die Live-Website stellt dasselbe Modul unter /helloworld bereit. Die Ausgabe stammt von app/modules/HelloWorld/Controllers/Home.php, das views/hello.view.php rendert.
Den Ablauf verstehen
module.init.phpaktiviert das Modul für/helloworldund/helloworld/*.- Statische Routen ordnen beide Schrägstrich-Varianten
HelloWorld:Home@index!zu. Home::indexerzeugt HTML mitRenderer::new()->module('HelloWorld')->setView('hello').- Die Dokumentationswebsite liefert
/aus dem Docs-Modul. HelloWorld ist unter/helloworlderreichbar.
Glückwunsch
Als Nächstes fügen Sie ein Layout-Include und ein benanntes Formular hinzu. Wechseln Sie zu Einführung in das Templatesystem.
Einführung in das Templatesystem
Hello World hat bereits eine View gerendert. Dieser Abschnitt benennt die Bausteine, damit Sie die Seite erweitern können: Dateien, die Fassade Renderer und die Direktiven {{ … }}. Die vollständige Referenz finden Sie im Dokumentationshub: Templatesystem.
Dateien
- View —
app/modules/{Module}/views/{name}.view.php, ausgewählt mitsetView('name'). - Layout —
app/modules/{Module}/views/layouts/{path}.layout.php, ausgewählt mitsetLayout('path')oder eingebunden als{{ layout:path }}. - Assets —
app/modules/{Module}/assets/..., ausgeliefert als/assets/modules/{Module}/....
{{ layout:h1-test }} lädt views/layouts/h1-test.layout.php. Stellen Sie dem Namen kein layouts/ voran.
Renderer
$html = Renderer::new()
->module('HelloWorld')
->setView('hello')
->setViewVar('title', 'Hello World')
->renderView();
if ($html === '') {
return new Response(500, 'Template error');
}
- Rufen Sie
setView()vorsetViewVar()auf. - Das zweite Argument von
setView()ist eine Fallback-View, kein Wrapper-Layout. - Eine fehlende Datei gibt
""zurück — keine Exception. Prüfen Sie die Zeichenkette. renderView()sieht nur View-Variablen. Übergeben Sie alles übersetViewVar().
Direktiven
| Schreibweise | Bedeutung |
|---|---|
{{ var: $title }} |
Gibt einen Wert aus. Nicht {{ $title }}. |
{{ if … }} … {{ /if }} |
Bedingung. Leerzeichen nach {{. |
{{ foreach $items as $item }} … {{ /foreach }} |
Schleife. |
{{ layout:partials/header }} |
Bindet eine Layout-Datei ein. |
{{ content }} |
Platzhalter für setLayout(), wenn Sie renderView() aufrufen. |
{{ formName(saveItem) }} |
Zwischen <fo-rm method="POST"> und </fo-rm>. |
{{ enc(key): $id }} |
Verschlüsselt ein Feld. Entschlüsseln Sie mit demselben Schlüssel. |
{{_ "Login" }} |
Übersetzt eine Zeichenkette. |
Laden Sie /assets/dotapp/dotapp.js auf Seiten, die <fo-rm> absenden oder $dotapp().load() aufrufen.
Wie geht es weiter
Der nächste Abschnitt fügt Hello World eine Notizen-Seite hinzu: ein Layout-Include, ein benanntes Formular und form() im Controller. Diese zusätzliche Route ist eine lokale Übung — sie ist nicht auf der öffentlichen Demo. Für jede Direktive und die Render-Pipeline öffnen Sie Templatesystem.
Hello World mit Formular und Layout
Erweitern Sie das Live-Modul HelloWorld in Ihrer eigenen Kopie des Projekts. Sie fügen /helloworld/notes hinzu, binden ein kleines Layout ein und verarbeiten ein benanntes Formular. Die öffentliche Website behält nur /helloworld.
Schritt 1: Route
In app/modules/HelloWorld/module.init.php, neben den vorhandenen Routen für /helloworld:
Router::match(
['GET', 'POST'],
['/helloworld/notes', '/helloworld/notes/'],
'HelloWorld:Home@index2!',
Router::STATIC_ROUTE
);
initializeRoutes() gibt bereits /helloworld/* zurück, daher wird der neue Pfad mit dem Modul geladen. Das ! an der Controller-Zeichenkette deaktiviert die Dependency Injection; die Methode erhält nur $request.
Schritt 2: Layout
Erstellen Sie app/modules/HelloWorld/views/layouts/notes-heading.layout.php:
<h1>{{ var: $heading }}</h1>
Schritt 3: View
Erstellen Sie app/modules/HelloWorld/views/notes.view.php. {{ formName(saveNote) }} steht innerhalb von <fo-rm>. Das Formular hat kein action und sendet daher an die aktuelle URL.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ var: $title }}</title>
<link rel="stylesheet" href="/assets/modules/HelloWorld/css/hello.css" />
</head>
<body>
<p>{{ var: $lead }}</p>
{{ if $saved }}
<p>You submitted: {{ var: $saved }}</p>
{{ /if }}
<fo-rm method="POST" id="noteForm">
<label for="note">Note</label>
<input type="text" id="note" name="note" placeholder="Text to echo" />
{{ formName(saveNote) }}
<button type="submit">{{ var: $btnText }}</button>
</fo-rm>
<h2>Tips from foreach</h2>
<ul>
{{ foreach $tips as $tip }}
<li>{{ var: $tip }}</li>
{{ /foreach }}
</ul>
<p><a href="/helloworld">Back to Hello World</a></p>
<script src="/assets/dotapp/dotapp.js"></script>
</body>
</html>
Diese Seite verwendet kein AJAX, daher ist dotapp.js für ein klassisches POST optional. Behalten Sie das Skript, wenn Sie später $dotapp().form('#noteForm') wie in der Demo sichere Formulare anbinden.
Schritt 4: Controller
Fügen Sie index2 in app/modules/HelloWorld/Controllers/Home.php hinzu. Übergeben Sie form() immer einen Fehler-Callback. Übergeben Sie $request->getPath(), damit der verschlüsselte Handler zur gesendeten URL passt (mit oder ohne abschließenden Schrägstrich).
public static function index2($request)
{
$saved = '';
$request->form(['POST'], 'saveNote', function ($request) use (&$saved) {
$saved = (string) ($request->data()['note'] ?? '');
}, function () {
// Required. Runs when the name does not match or the signature is invalid.
}, $request->getPath());
$html = Renderer::new()
->module('HelloWorld')
->setView('notes')
->setViewVar('title', 'Notes')
->setViewVar('heading', 'Notes')
->setViewVar('lead', 'Submit a line of text. The next render shows it below the heading.')
->setViewVar('btnText', 'Save')
->setViewVar('saved', $saved)
->setViewVar('tips', [
'setView() before setViewVar()',
'formName stays between fo-rm tags',
'Empty renderView() means a missing file',
])
->renderView();
if ($html === '') {
Logger::use()->error('HelloWorld notes view produced empty output');
return new Response(500, 'Template error');
}
return $html;
}
$request->data() ist der XSS-geschützte Datenbeutel, den Sie zum Ausgeben verwenden sollten. Verwenden Sie $request->data(true), wenn Sie Geheimnisse entschlüsseln oder vergleichen. Bauen Sie keine HTML-Zeichenketten im Controller — übergeben Sie Daten und formatieren Sie sie in der View.
Ausprobieren
Vom Projektstamm aus:
php -S 127.0.0.1:8000
Öffnen Sie http://127.0.0.1:8000/helloworld/notes. Sie sollten die Überschrift aus dem Layout, drei Tipps aus foreach und das Formular sehen. Senden Sie Text; die Seite wird neu geladen und zeigt den geschützten Wert.
Weiter: Live ausprobieren für die öffentliche Hello-World-Seite oder die vollständige Referenz zum Templatesystem (Direktiven, Assets, eigene Renderer, Sandbox).
Live ausprobieren
Das Modul HelloWorld aus dieser Anleitung läuft auf dieser Website. Sie benötigen keinen lokalen Server, um die erste Seite zu sehen.
Hello World
Öffnen Sie /helloworld. Das ist HelloWorld:Home@index!, das views/hello.view.php mit Renderer::new() rendert.
Notizen-Seite (nur lokal)
Die Übung mit Formular und Layout aus dem vorherigen Abschnitt (/helloworld/notes) ist hier nicht bereitgestellt. Fügen Sie diese Route in Ihrer eigenen Kopie hinzu und vergleichen Sie sie mit der öffentlichen Seite.
Was Sie als Nächstes lesen sollten
- Templatesystem — alle Direktiven, Assets, eigene Renderer, Sandbox.
- Sichere Formulare —
fo-rm, CRC, verschlüsselte Felder. - Beispiele — Live-Demos.