Zum Inhalt springen

Framework DotApp Aktualisiert: 2026-08-19


Über den Autor

Mein Name ist Štefan Miščík und ich bin Senior-Fullstack-Webentwickler bei Dotsystems s.r.o. (WEB)

Designziele

DotApp ist ein PHP-Framework für Anwendungen jeder Größe. Die Anwendungslogik liegt in Modulen. Jedes Modul besitzt seine eigenen Routen, Controller, Middleware, Views und Assets.

Die Arbeit an DotApp begann 2014 als vollständige Anwendungsarchitektur: Routing, Rendering, Sicherheit und die Datenbankschicht teilen sich eine Laufzeitumgebung und ein gemeinsames Regelwerk.


Konventionen

Die öffentliche API verwendet Fassaden, Modul-Controller und eine kleine Menge an Konventionen:

Fassaden

Fassaden (Router, Route, DB, Request, Renderer::new()) sind die öffentliche API für Kerndienste. Anwendungsrouten werden in der module.init.php jedes Moduls registriert.

Router- und Route-Fassaden

Verwenden Sie die Fassaden Router und Route (sie sind Aliase voneinander) in module.init.php. Beispiel: Router::get('/helloworld', 'HelloWorld:Home@index!', Router::STATIC_ROUTE).


// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/helloworld', fn() => 'Hello World', Router::STATIC_ROUTE);
Route::get('/helloworld', fn() => 'Hello World', Router::STATIC_ROUTE);
Router::get('/helloworld', 'HelloWorld:Home@index!', Router::STATIC_ROUTE);
Route::get('/helloworld', 'HelloWorld:Home@index!', Router::STATIC_ROUTE);
                    
DB-Fassade

Verwenden Sie die DB-Fassade. Abfragen erfolgen mit DB::module('RAW').


DB::module('RAW')->q(function ($qb) {
    $qb->select(['id', 'title'])->from('helloworld_notes')->where('id', '=', 1);
})->all();
                    
Request-Fassade

In Controllern lesen Sie die aktuelle Anfrage aus dem Argument $request. Die Request-Fassade steht zur Verfügung, wenn Sie sich außerhalb eines Controller-Callbacks befinden.


Request::getPath(); // Get the current request path
Request::getMethod(); // Get the HTTP method (e.g., GET, POST)
Request::data(); // Access request data (e.g., POST or JSON payload)
$request->form(['POST'], 'myForm', function ($request) {
    return 'Form submitted!';
}, function () {
    return 'Invalid form';
});
                    


Die DotApp-Instanz

Routing, Datenbank, Rendering, Konfiguration und Sitzungsspeicher verwenden Fassaden: Router::, DB::, Renderer::new(), Config::, DSM::use(). Wenn Sie den Kernel selbst benötigen (Ereignisse, unprotect, ajaxReply, call), holen Sie ihn mit:


use \Dotsystems\App\DotApp;
$dotApp = DotApp::DotApp();
            

Registrieren Sie Routen mit Router::get (und den übrigen Verb-Methoden) innerhalb der Methode initialize($dotApp) des Moduls.



Wichtige Funktionen von DotApp

Einfachheit ohne Kompromisse

DotApp verbindet intuitives Design mit hoher Leistung. Sie benötigen keine komplexen Setups oder übermäßige Konfiguration – definieren Sie einfach Routen und Module, und alles andere organisiert sich selbst. Routen werden nur dort verarbeitet, wo sie benötigt werden, und es sind keine zusätzlichen Schritte erforderlich, um die Leistung zu halten – alles läuft automatisch und effizient.


// Example of simplicity when working with the DotApp framework
namespace Dotsystems\App\Modules\HelloWorld\Controllers;

class TestController1 extends \Dotsystems\App\Parts\Controller {
    public static function testMiddlewareFn($request) {
        return "Hello " . $request->body(); // Adds text at the beginning
    }
    
    public static function mainFn($request) {
        return $request->body() . "World"; // Adds text at the end
    }
}

// Simple controller call
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get("/home", "HelloWorld:TestController1@mainFn!", Router::STATIC_ROUTE)
    ->before("HelloWorld:TestController1@testMiddlewareFn!");

// Result for /home: "Hello World"
            
Fokus auf geringen Ressourcenverbrauch

DotApp hält den Speicherbedarf auf einem Minimum – statt massive Routenstrukturen und Konfigurationen zu laden, verarbeitet es nur, was gerade benötigt wird. Das bedeutet schnelleren Start und gute Leistung auch auf schwächeren Servern.

Schnelle Routenverarbeitung

DotApp filtert intelligent nur relevante Module und deren Routen und vermeidet unnötige Suchvorgänge. Das Ergebnis ist schnelles Laden selbst bei Tausenden von Routen.

Beispiel

Demonstration der Routing-Geschwindigkeit: Vor der Anzeige dieser Seite wurden automatisch 1000 eindeutige statische und 1000 eindeutige dynamische, absichtlich unsortierte Routen zufällig zum Router hinzugefügt. Ziel war es, das schnelle Laden trotz 2000 zusätzlicher, unnötiger Routen zu zeigen. Keine davon passt zur aktuellen URL, sodass alle den Matching-Prozess des Routers durchlaufen müssen.


$p = rtrim((string) Config::module('Docs', 'prefix'), '/') ?: '/documentation';

for ($i = 0; $i < 1000; $i++) {
    $path = $p . '/_routa' . $i;
    Router::any($path, function () use ($path) {
        return "This is route: " . $path;
    }, Router::STATIC_ROUTE);
}

for ($i = 0; $i < 1000; $i++) {
    $path = $p . '/_routa' . $i . '(?:/{language})?';
    Router::any($path, function () use ($path) {
        return "This is route: " . $path;
    });
}

// Try it out: /documentation/_routa7
                            


Die Anzeige der Seite inklusive Routenerstellung, Routing und Codegenerierung über das Vorlagensystem dauerte:

PHP version: 8.3.15 fpm-fcgi
Script execution time: 0.043574 s
Memory used by the script: 1019.92 KB
Peak memory usage: 1.56 MB
Loaded modules: 6

Modulare Effizienz mit bidirektionaler Verbindung

DotApp verarbeitet nur die Routen des aktiven Moduls und spart so Ressourcen. Module können einander laden: Der Listener eines Moduls kann ein anderes laden, und ein übergeordnetes Modul kann Kindmodule aktivieren. Kombinationen bleiben in module.listeners.php und initializeRoutes() explizit.

Kaskadierendes Laden von Modulen

Wenn ein Modul von einem anderen abhängt (z. B. BBB benötigt XXX), lädt DotApp XXX automatisch, bevor BBB abgeschlossen wird. Das gewährleistet Zuverlässigkeit – keine Fehler durch fehlende Abhängigkeiten – und hält das System schlank, indem nur das Nötige geladen wird.

Dynamische Abhängigkeitsverwaltung über Trigger und Listener

Jedes Modul hat Trigger wie init.start, loading, loaded und weitere, auf die Listener reagieren. Zum Beispiel kann der Listener dotapp.module.Module1.loading das Laden von Modul 2 auslösen, wenn Modul 1 aktiv ist. Die Funktion load() stellt sicher, dass ein Modul nur einmal geladen wird, unabhängig davon, ob kaskadierend (von oben nach unten) oder bidirektional (von unten nach oben).

Hinweis: Triggernamen sind unabhängig von Groß- und Kleinschreibung, daher sind dotapp.module.Module1.loading und Dotapp.Module.Module1.Loading gleichwertig. Für Konsistenz empfehlen wir jedoch das Format dotapp.module.ClassName.eventName.


use Dotsystems\App\DotApp;
use Dotsystems\App\Parts\Events;

Events::on("dotapp.module.Shop.loading", function () {
    DotApp::DotApp()->module("Cart")->load();
});
            
Automatische Auflösung von Abhängigkeiten und DI

Module und ihre Abhängigkeiten werden automatisch geladen – definieren Sie die Logik einfach in initializeCondition() oder in Listenern. Dependency Injection (DI) ist einfach und effizient – Dienste werden registriert (z. B. singleton), und DotApp liefert sie dort, wo sie benötigt werden, ohne unnötigen Overhead.

Registrieren Sie Dienste in der initialize($dotApp) des Moduls mit singleton / bind. Controller sind public static und nehmen $request entgegen.


public function initialize($dotApp) {
    $dotApp->singleton('cache', function () {
        return new CacheService();
    });
}

namespace Dotsystems\App\Modules\HelloWorld\Controllers;

class Home extends \Dotsystems\App\Parts\Controller {
    public static function index($request) {
        $cache = \Dotsystems\App\DotApp::DotApp()->resolve('cache');
        return "Hello World";
    }
}
            
Der erste Callback gewinnt

Für jede URL wird nur der erste passende Callback behalten – nachfolgende Registrierungsversuche werden ignoriert. Das steigert die Leistung und verhindert Konflikte.


Router::get('/documentation/test1', "HelloWorld:Home@index!");
Router::get('/documentation/test1', function () { return "Ignored"; });
// Only the first definition is used
            
Skalierbarkeit für kleine und große Projekte

DotApp eignet sich gleichermaßen für kleine Websites und komplexe Anwendungen – es behält niedrige Anforderungen und hohe Geschwindigkeit unabhängig vom Projektumfang bei. Große Module können in kleinere Teile aufgeteilt werden, die bei Bedarf rekursiv geladen werden.

Kein unnötiger Overhead

DotApp konzentriert sich auf das Wesentliche – schnelles Routing, minimaler Ressourcenverbrauch und einfache Nutzung. Es belastet Sie nicht mit Funktionen, die Sie nicht brauchen.

Vorlagensystem

Views und Layouts liegen im Modul. Geben Sie mit {{ var: $title }} aus, binden Sie Fragmente mit {{ layout:partials/header }} ein, und rendern Sie aus einem Controller mit Renderer::new()->module('HelloWorld')->setView('hello'). Vollständige Referenz: Vorlagensystem.

DotApp Bridge

Live-Verbindung – eine Brücke zwischen Frontend und Backend. Verwenden Sie einfach folgenden Code:

<button {{ dotbridge:on(click)="newsletter.subscribe(newsletter.email)" }}>Subscribe</button>

und auf der PHP-Seite in der initialize() des Moduls:


use Dotsystems\App\Parts\Bridge;
use Dotsystems\App\Parts\Router;

$urls = ['/newsletter', '/newsletter/'];
Bridge::listen($urls, "newsletter.subscribe", function ($request) {
    $email = $request->data(true)['data']['newsletter.email'] ?? '';
    return ['ok' => true, 'email' => $email];
}, Router::STATIC_ROUTE);
            

Die Schaltfläche wird automatisch mit der PHP-Funktion verknüpft; die Dokumentation stellt die vielfältigen Möglichkeiten vor.

Beispiel für generierten Code:


<button  dotbridge-key="xMMp1qEHRKIdpa-p@DBqK7fKPbw@XaU" dotbridge-id="tEFJfIwAHrf5P3VyEiRgi8jfebFRvCJ36PSObPuCYsKRSV720260819401340134013121213409559e2fd45c02694b31e3ade539a0dd9" dotbridge-event="click" dotbridge-data="EGGfhUtkRrOH7FuBuXpyXzBJUkx3dzJLWG1UQWExVC9GMXR3RTNsOFdCTHVvTWRRMEUwaW00NVVLQzg9" dotbridge-data-id="5qNlSyCDW9kRBgNP1akN7U13TEJiT3VvRHphb0pJcXdES0dvRC95Y3JpRVJPL3FjMTNtU3hOYVVsc1kwOGhtQWZlWG5aNDBrWDJURTlSZ0txNEpoellvTzFtTFpkYkZoS1ZMYnlsMTNWQjNaL053RjU2eGxrNlUwMW53PQ==" dotbridge-function="newsletter.subscribe" dotbridge-inputs="newsletter.email">Subscribe</button>
            
HTML

DotApp ist maßgeschneidert für Entwickler, die ein effizientes Werkzeug ohne Ballast wollen. Es bietet Geschwindigkeit, geringe Anforderungen und eine Einfachheit, die die Arbeit erleichtert. Es ist ein Framework, das beweist, dass weniger mehr sein kann – mit Ergebnissen, die für sich sprechen.

Probieren Sie DotApp aus und überzeugen Sie sich selbst!