Learn

Erfahren Sie mehr über Flight

Flight ist ein schnelles, einfaches, erweiterbares Framework für PHP. Es ist ziemlich vielseitig und kann für den Aufbau jeder Art von Webanwendung verwendet werden. Es ist mit Einfachheit im Sinn entwickelt und so geschrieben, dass es leicht zu verstehen und zu verwenden ist.

Wichtige Framework-Konzepte

Warum ein Framework?

Hier ist ein kurzer Artikel darüber, warum Sie ein Framework verwenden sollten. Es ist eine gute Idee, die Vorteile der Verwendung eines Frameworks zu verstehen, bevor Sie eines verwenden.

Zusätzlich wurde ein ausgezeichnetes Tutorial von @lubiana erstellt. Obwohl es nicht im Detail auf Flight eingeht, wird Ihnen dieser Leitfaden helfen, einige der wichtigsten Konzepte rund um ein Framework zu verstehen und warum sie von Vorteil sind. Sie finden das Tutorial hier.

Kernthemen

Autoloading

Erfahren Sie, wie Sie Ihre eigenen Klassen in Ihrer Anwendung automatisch laden können.

Routing

Erfahren Sie, wie Sie Routen für Ihre Webanwendung verwalten können. Dies beinhaltet auch das Gruppieren von Routen, Routenparameter und Middleware.

Middleware

Erfahren Sie, wie Sie Middleware verwenden können, um Anfragen und Antworten in Ihrer Anwendung zu filtern.

Requests

Erfahren Sie, wie Sie Anfragen und Antworten in Ihrer Anwendung verarbeiten können.

Responses

Erfahren Sie, wie Sie Antworten an Ihre Benutzer senden können.

HTML-Vorlagen

Erfahren Sie, wie Sie den integrierten Ansichtsmotor verwenden können, um Ihre HTML-Vorlagen zu rendern.

Sicherheit

Erfahren Sie, wie Sie Ihre Anwendung vor gängigen Sicherheitsbedrohungen schützen können.

Konfiguration

Erfahren Sie, wie Sie das Framework für Ihre Anwendung konfigurieren können.

Flight erweitern

Erfahren Sie, wie Sie das Framework erweitern können, indem Sie Ihre eigenen Methoden und Klassen hinzufügen.

Ereignisse und Filterung

Erfahren Sie, wie Sie das Ereignissystem verwenden können, um Hooks zu Ihren Methoden und internen Framework-Methoden hinzuzufügen.

Dependency Injection Container

Erfahren Sie, wie Sie Dependency Injection-Container (DIC) verwenden können, um die Abhängigkeiten Ihrer Anwendung zu verwalten.

Framework-API

Erfahren Sie mehr über die Kernmethoden des Frameworks.

Migration auf v3

Die Abwärtskompatibilität wurde größtenteils beibehalten, aber es gibt einige Änderungen, über die Sie Bescheid wissen sollten, wenn Sie von v2 auf v3 migrieren.

Learn/stopping

Anhalten

Sie können das Framework jederzeit durch Aufrufen der halt Methode stoppen:

Flight::halt();

Sie können auch einen optionalen HTTP-Statuscode und eine Nachricht angeben:

Flight::halt(200, 'Bin gleich wieder da...');

Das Aufrufen von halt verwirft jeglichen Antwortinhalt bis zu diesem Zeitpunkt. Wenn Sie das Framework anhalten und die aktuelle Antwort ausgeben möchten, verwenden Sie die stop Methode:

Flight::stop();

Learn/errorhandling

Fehlerbehandlung

Fehler und Ausnahmen

Alle Fehler und Ausnahmen werden von Flight abgefangen und an die error Methode übergeben. Das Standardverhalten besteht darin, eine generische HTTP 500 Interner Serverfehler Antwort mit einigen Fehlerinformationen zu senden.

Sie können dieses Verhalten nach Ihren eigenen Bedürfnissen überschreiben:

Flight::map('error', function (Throwable $error) {
  // Fehler behandeln
  echo $error->getTraceAsString();
});

Standardmäßig werden Fehler nicht im Webserver protokolliert. Sie können dies aktivieren, indem Sie die Konfiguration ändern:

Flight::set('flight.log_errors', true);

Nicht gefunden

Wenn eine URL nicht gefunden werden kann, ruft Flight die notFound Methode auf. Das Standardverhalten besteht darin, eine HTTP 404 Nicht gefunden Antwort mit einer einfachen Nachricht zu senden.

Sie können dieses Verhalten nach Ihren eigenen Bedürfnissen überschreiben:

Flight::map('notFound', function () {
  // Nicht gefunden behandeln
});

Learn/migrating_to_v3

Migration zu v3

Die Abwärtskompatibilität wurde größtenteils beibehalten, aber es gibt einige Änderungen, über die Sie Bescheid wissen sollten, wenn Sie von v2 auf v3 migrieren.

Ausgabepufferverhalten (3.5.0)

Output-Pufferung ist der Prozess, bei dem die Ausgabe, die von einem PHP-Skript generiert wird, in einem Puffer (intern zu PHP) gespeichert wird, bevor sie an den Client gesendet wird. Dies ermöglicht es Ihnen, die Ausgabe zu ändern, bevor sie an den Client gesendet wird.

In einer MVC-Anwendung ist der Controller der "Manager" und er verwaltet, was die Ansicht tut. Das Generieren von Ausgaben außerhalb des Controllers (oder in Flights Fall manchmal eine anonyme Funktion) bricht das MVC-Muster. Diese Änderung soll mehr im Einklang mit dem MVC-Muster sein und das Framework vorhersehbarer und einfacher zu verwenden machen.

In v2 wurde die Ausgabepufferung so behandelt, dass sie ihren eigenen Ausgabepuffer nicht konsistent schloss, was Unittests und Streaming erschwerte. Für die Mehrheit der Benutzer dürfte diese Änderung Sie tatsächlich nicht beeinflussen. Wenn Sie jedoch Inhalte außerhalb von Aufrufbaren und Controllern ausgeben (zum Beispiel in einem Hook), werden Sie wahrscheinlich auf Probleme stoßen. Das Ausgeben von Inhalten in Hooks und vor der tatsächlichen Ausführung des Frameworks hat möglicherweise in der Vergangenheit funktioniert, aber es wird zukünftig nicht mehr funktionieren.

Wo Sie möglicherweise Probleme haben

// index.php
require 'vendor/autoload.php';

// nur ein Beispiel
define('STARTZEIT', microtime(true));

function hallo() {
    echo 'Hallo Welt';
}

Flight::map('hallo', 'hallo');
Flight::after('hallo', function(){
    // das wird tatsächlich in Ordnung sein
    echo '<p>Dieser Hallo-Welt-Satz wurde Ihnen vom Buchstaben "H" präsentiert</p>';
});

Flight::before('start', function(){
    // Dinge wie diese führen zu einem Fehler
    echo '<html><head><title>Meine Seite</title></head><body>';
});

Flight::route('/', function(){
    // dies ist eigentlich in Ordnung
    echo 'Hallo Welt';

    // Dies sollte auch in Ordnung sein
    Flight::hallo();
});

Flight::after('start', function(){
    // das wird einen Fehler verursachen
    echo '<div>Ihre Seite wurde in '.(microtime(true) - STARTZEIT).' Sekunden geladen</div></body></html>';
});

Aktivieren des v2-Renderingverhaltens

Können Sie Ihren alten Code so lassen, wie er ist, ohne eine Neuschreibung vorzunehmen, um ihn mit v3 zum Laufen zu bringen? Ja, können Sie! Sie können das v2-Renderingverhalten aktivieren, indem Sie die Konfigurationsoption flight.v2.output_buffering auf true setzen. Dadurch können Sie das alte Renderingverhalten weiterhin verwenden, aber es wird empfohlen, es zukünftig zu beheben. In v4 des Frameworks wird dies entfernt sein.

// index.php
require 'vendor/autoload.php';

Flight::set('flight.v2.output_buffering', true);

Flight::before('start', function(){
    // Jetzt wird das in Ordnung sein
    echo '<html><head><title>Meine Seite</title></head><body>';
});

// mehr Code 

Dispatcher-Änderungen (3.7.0)

Wenn Sie bisher statische Methoden für Dispatcher wie Dispatcher::invokeMethod() oder Dispatcher::execute() direkt aufgerufen haben, müssen Sie Ihren Code aktualisieren, um diese Methoden nicht mehr direkt aufzurufen. Dispatcher wurde in eine mehr objektorientierte Form konvertiert, damit Dependency Injection Container auf eine einfachere Weise verwendet werden können. Wenn Sie eine Methode ähnlich wie Dispatcher aufrufen müssen, können Sie manuell etwas wie $ergebnis = $klasse->$methode(...$parameter); oder call_user_func_array() verwenden.

Learn/configuration

Konfiguration

Sie können bestimmte Verhaltensweisen von Flight anpassen, indem Sie Konfigurationswerte über die set-Methode festlegen.

Flight::set('flight.log_errors', true);

Verfügbare Konfigurationseinstellungen

Folgende Liste enthält alle verfügbaren Konfigurationseinstellungen:

Variablen

Flight ermöglicht es Ihnen, Variablen zu speichern, damit sie überall in Ihrer Anwendung genutzt werden können.

// Speichere deine Variable
Flight::set('id', 123);

// Anderswo in deiner Anwendung
$id = Flight::get('id');

Um zu prüfen, ob eine Variable gesetzt wurde, können Sie Folgendes tun:

if (Flight::has('id')) {
  // Etwas tun
}

Sie können eine Variable löschen, indem Sie Folgendes tun:

// Löscht die id-Variable
Flight::clear('id');

// Löscht alle Variablen
Flight::clear();

Flight verwendet auch Variablen für Konfigurationszwecke.

Flight::set('flight.log_errors', true);

Fehlerbehandlung

Fehler und Ausnahmen

Alle Fehler und Ausnahmen werden von Flight erfasst und an die error-Methode weitergeleitet. Das Standardverhalten besteht darin, eine allgemeine HTTP 500 Internal Server Error-Antwort mit einigen Fehlerinformationen zu senden.

Sie können dieses Verhalten nach Ihren eigenen Bedürfnissen überschreiben:

Flight::map('error', function (Throwable $error) {
  // Fehler behandeln
  echo $error->getTraceAsString();
});

Standardmäßig werden Fehler nicht im Webserverprotokoll protokolliert. Sie können dies aktivieren, indem Sie die Konfiguration ändern:

Flight::set('flight.log_errors', true);

Nicht gefunden

Wenn eine URL nicht gefunden werden kann, ruft Flight die Methode notFound auf. Das Standardverhalten besteht darin, eine HTTP 404 Not Found-Antwort mit einer einfachen Meldung zu senden.

Sie können dieses Verhalten nach Ihren eigenen Bedürfnissen überschreiben:

Flight::map('notFound', function () {
  // Nicht gefunden behandeln
});

Learn/security

Sicherheit

Sicherheit ist ein wichtiges Thema, wenn es um Webanwendungen geht. Sie möchten sicherstellen, dass Ihre Anwendung sicher ist und die Daten Ihrer Benutzer geschützt sind. Flight bietet eine Reihe von Funktionen, um Ihnen bei der Sicherung Ihrer Webanwendungen zu helfen.

Header

HTTP-Header sind eine der einfachsten Möglichkeiten, um Ihre Webanwendungen abzusichern. Sie können Header verwenden, um Clickjacking, XSS und andere Angriffe zu verhindern. Es gibt mehrere Möglichkeiten, wie Sie diese Header zu Ihrer Anwendung hinzufügen können.

Zwei großartige Websites, um die Sicherheit Ihrer Header zu überprüfen, sind securityheaders.com und observatory.mozilla.org.

Manuell hinzufügen

Sie können diese Header manuell hinzufügen, indem Sie die header-Methode auf dem Flight\Response-Objekt verwenden.

Diese können am Anfang Ihrer bootstrap.php oder index.php Dateien hinzugefügt werden.

Als Filter hinzufügen

Sie können sie auch in einem Filter/Hook wie folgt hinzufügen:

Als Middleware hinzufügen

Sie können sie auch als Middleware-Klasse hinzufügen. Dies ist eine gute Möglichkeit, Ihren Code sauber und organisiert zu halten.

Cross Site Request Forgery (CSRF)

Cross Site Request Forgery (CSRF) ist eine Art von Angriff, bei dem eine bösartige Website den Browser eines Benutzers dazu bringen kann, eine Anfrage an Ihre Website zu senden. Flight bietet keinen eingebauten CSRF-Schutzmechanismus, aber Sie können leicht Ihren eigenen implementieren, indem Sie Middleware verwenden.

Einrichtung

Zuerst müssen Sie ein CSRF-Token generieren und es in der Sitzung des Benutzers speichern. Sie können dann dieses Token in Ihren Formularen verwenden und es beim Absenden des Formulars überprüfen.

Verwendung von Latte

Sie können auch eine benutzerdefinierte Funktion einstellen, um das CSRF-Token in Ihren Latte-Templates auszugeben.

Und jetzt können Sie in Ihren Latte-Templates die csrf()-Funktion verwenden, um das CSRF-Token auszugeben.

Überprüfen des CSRF-Token

Sie können das CSRF-Token mithilfe von Eventfiltern überprüfen.

Oder Sie können eine Middleware-Klasse verwenden.

Cross Site Scripting (XSS)

Cross Site Scripting (XSS) ist eine Art von Angriff, bei dem eine bösartige Website Code in Ihre Website einschleusen kann. Die meisten dieser Möglichkeiten stammen aus Formularwerten, die Ihre Endbenutzer ausfüllen. Sie sollten niemals Ausgaben Ihrer Benutzer vertrauen! Gehen Sie immer davon aus, dass alle von ihnen die besten Hacker der Welt sind. Sie können bösartiges JavaScript oder HTML in Ihre Seite einschleusen. Dieser Code kann verwendet werden, um Informationen von Ihren Benutzern zu stehlen oder Aktionen auf Ihrer Website auszuführen. Durch die Verwendung der View-Klasse von Flight können Sie Ausgaben einfach escapen, um XSS-Angriffe zu verhindern.

SQL Injection

SQL Injection ist eine Art von Angriff, bei dem ein bösartiger Benutzer SQL-Code in Ihre Datenbank einschleusen kann. Dies kann verwendet werden, um Informationen aus Ihrer Datenbank zu stehlen oder Aktionen auf Ihrer Datenbank auszuführen. Wieder sollten Sie niemals Eingaben Ihrer Benutzer vertrauen! Gehen Sie immer davon aus, dass sie es auf Ihr Blut abgesehen haben. Sie können mit vorbereiteten Anweisungen in Ihren PDO-Objekten SQL-Injektionen verhindern.

CORS

Cross-Origin Resource Sharing (CORS) ist ein Mechanismus, der es vielen Ressourcen (z. B. Schriften, JavaScript usw.) auf einer Webseite ermöglicht, von einer anderen Domain außerhalb der Domain, von der die Ressource stammt, angefordert zu werden. Flight hat keine integrierte Funktionalität, aber dies kann leicht mit Middleware oder Eventfiltern wie bei CSRF gehandhabt werden.

Fazit

Sicherheit ist wichtig, und es ist wichtig sicherzustellen, dass Ihre Webanwendungen sicher sind. Flight bietet eine Reihe von Funktionen, um Ihnen bei der Sicherung Ihrer Webanwendungen zu helfen, aber es ist wichtig, immer wachsam zu sein und sicherzustellen, dass Sie alles tun, um die Daten Ihrer Benutzer zu schützen. Gehen Sie immer vom Schlimmsten aus und vertrauen Sie niemals den Eingaben Ihrer Benutzer. Escapen Sie immer Ausgaben und verwenden Sie vorbereitete Anweisungen, um SQL-Injektionen zu verhindern. Verwenden Sie immer Middleware, um Ihre Routen vor CSRF- und CORS-Angriffen zu schützen. Wenn Sie all dies tun, sind Sie auf dem besten Weg, sichere Webanwendungen zu erstellen.

Learn/overriding

Überschreiben

Flight ermöglicht es Ihnen, seine Standardfunktionalität anzupassen, um Ihren eigenen Anforderungen gerecht zu werden, ohne dass Sie Code ändern müssen.

Zum Beispiel, wenn Flight eine URL nicht mit einer Route übereinstimmen kann, ruft es die notFound-Methode auf, die eine generische HTTP 404-Antwort sendet. Sie können dieses Verhalten überschreiben, indem Sie die map-Methode verwenden:

Flight::map('notFound', function() {
  // Benutzerdefinierte 404-Seite anzeigen
  include 'errors/404.html';
});

Flight ermöglicht es Ihnen auch, Kernkomponenten des Frameworks zu ersetzen. Zum Beispiel können Sie die Standard-Routerklasse durch Ihre eigene benutzerdefinierte Klasse ersetzen:

// Registrieren Sie Ihre benutzerdefinierte Klasse
Flight::register('router', MyRouter::class);

// Wenn Flight die Router-Instanz lädt, wird Ihre Klasse geladen
$myrouter = Flight::router();

Framework-Methoden wie map und register können jedoch nicht überschrieben werden. Sie erhalten einen Fehler, wenn Sie es zu versuchen.

Learn/routing

Routen

Hinweis: Möchten Sie mehr über Routenverständnis erfahren? Werfen Sie einen Blick auf die "Warum ein Framework?" Seite für eine detailliertere Erklärung.

Die grundlegende Routenführung in Flight erfolgt durch das Zuordnen eines URL-Musters mit einer Rückruffunktion oder einem Array einer Klasse und Methode.

Flight::route('/', function(){
    echo 'Hallo Welt!';
});

Routen werden in der Reihenfolge abgeglichen, in der sie definiert sind. Die erste Route, die eine Anfrage abgleicht, wird aufgerufen.

Rückrufe/Funktionen

Der Rückruf kann jedes Objekt sein, das aufrufbar ist. Sie können also eine reguläre Funktion verwenden:

function hallo(){
    echo 'Hallo Welt!';
}

Flight::route('/', 'hallo');

Klassen

Sie können auch eine statische Methode einer Klasse verwenden:

class Begrüßung {
    public static function hallo() {
        echo 'Hallo Welt!';
    }
}

Flight::route('/', [ 'Begrüßung','hallo' ]);

Oder indem Sie zuerst ein Objekt erstellen und dann die Methode aufrufen:


// Greeting.php
class Begrüßung
{
    public function __construct() {
        $this->name = 'Max Mustermann';
    }

    public function hallo() {
        echo "Hallo, {$this->name}!";
    }
}

// index.php
$begruessung = new Begrüßung();

Flight::route('/', [ $begruessung, 'hallo' ]);
// Sie können dies auch tun, ohne das Objekt zuerst zu erstellen
// Hinweis: Es werden keine Argumente in den Konstruktor eingesetzt
Flight::route('/', [ 'Begrüßung', 'hallo' ]);

Dependency Injection via DIC (Dependency Injection Container)

Wenn Sie die Dependency Injection über einen Container verwenden möchten (PSR-11, PHP-DI, Dice, etc), sind die einzigen Arten von Routen, bei denen dies verfügbar ist, entweder das direkte Erstellen des Objekts selbst und Verwendung des Containers zur Erstellung Ihres Objekts oder Sie können Zeichenfolgen verwenden, um die Klasse und Methode zum Aufrufen zu definieren. Sie können zur Dependency Injection Seite gehen für weitere Informationen.

Hier ist ein schnelles Beispiel:


use flight\database\PdoWrapper;

// Begrüßung.php
class Begrüßung
{
    protected PdoWrapper $pdoWrapper;
    public function __construct(PdoWrapper $pdoWrapper) {
        $this->pdoWrapper = $pdoWrapper;
    }

    public function hallo(int $id) {
        // etwas mit $this->pdoWrapper machen
        $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]);
        echo "Hallo, Welt! Mein Name ist {$name}!";
    }
}

// index.php

// Container mit den erforderlichen Parametern einrichten
// Siehe die Dependency Injection-Seite für mehr Informationen zu PSR-11
$dice = new \Dice\Dice();

// Vergessen Sie nicht, die Variable mit '$dice = 'neu zuzuweisen!
$dice = $dice->addRule('flight\database\PdoWrapper', [
    'shared' => true,
    'constructParams' => [ 
        'mysql:host=localhost;dbname=test', 
        'root',
        'passwort'
    ]
]);

// Container-Handler registrieren
Flight::registerContainerHandler(function($class, $params) use ($dice) {
    return $dice->create($class, $params);
});

// Routen wie gewohnt
Flight::route('/hallo/@id', [ 'Begrüßung', 'hallo' ]);
// oder
Flight::route('/hallo/@id', 'Begrüßung->hallo');
// oder
Flight::route('/hallo/@id', 'Begrüßung::hallo');

Flight::start();

Methoden-Routen

Standardmäßig werden Routenmuster gegen alle Anforderungsmethoden abgeglichen. Sie können auf bestimmte Methoden reagieren, indem Sie einen Bezeichner vor der URL platzieren.

Flight::route('GET /', function () {
  echo 'Ich habe eine GET-Anforderung erhalten.';
});

Flight::route('POST /', function () {
  echo 'Ich habe eine POST-Anforderung erhalten.';
});

// Sie können Flight::get() nicht für Routen verwenden, da dies eine Methode ist
//     um Variablen zu erhalten, nicht um eine Route zu erstellen.
// Flight::post('/', function() { /* Code */ });
// Flight::patch('/', function() { /* Code */ });
// Flight::put('/', function() { /* Code */ });
// Flight::delete('/', function() { /* Code */ });

Sie können auch mehrere Methoden auf einen einzigen Rückruf abbilden, indem Sie einen |-Trenner verwenden:

Flight::route('GET|POST /', function () {
  echo 'Ich habe entweder eine GET- oder eine POST-Anforderung erhalten.';
});

Zusätzlich können Sie das Router-Objekt abrufen, das einige Hilfsmethoden zum Verwenden hat:


$router = Flight::router();

// Verknüpft alle Methoden
$router->map('/', function() {
    echo 'Hallo Welt!';
});

// GET-Anforderung
$router->get('/benutzer', function() {
    echo 'Benutzer';
});
// $router->post();
// $router->put();
// $router->delete();
// $router->patch();

Reguläre Ausdrücke

Sie können reguläre Ausdrücke in Ihren Routen verwenden:

Flight::route('/benutzer/[0-9]+', function () {
  // Dies passt zu /benutzer/1234
});

Obwohl diese Methode verfügbar ist, wird empfohlen, benannte Parameter oder benannte Parameter mit regulären Ausdrücken zu verwenden, da sie lesbarer und einfacher zu warten sind.

Benannte Parameter

Sie können benannte Parameter in Ihren Routen angeben, die an Ihre Rückruffunktion übergeben werden.

Flight::route('/@name/@id', function (string $name, string $id) {
  echo "Hallo, $name ($id)!";
});

Sie können auch reguläre Ausdrücke mit Ihren benannten Parametern verwenden, indem Sie den :-Trenner verwenden:

Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) {
  // Dies passt zu /bob/123
  // Passt aber nicht zu /bob/12345
});

Hinweis: Das Abgleichen von Regex-Gruppen () mit benannten Parametern wird nicht unterstützt. :'(

Optionale Parameter

Sie können benannte Parameter angeben, die optional für den Abgleich sind, indem Sie Segmente in Klammern einschließen.

Flight::route(
  '/blog(/@year(/@month(/@day)))',
  function(?string $year, ?string $month, ?string $day) {
    // Dies passt zu folgenden URLs:
    // /blog/2012/12/10
    // /blog/2012/12
    // /blog/2012
    // /blog
  }
);

Nicht übereinstimmende optionale Parameter werden als NULL übergeben.

Platzhalter

Das Abgleichen erfolgt nur auf einzelnen URL-Segmenten. Wenn Sie mehrere Segmenten abgleichen möchten, können Sie den *-Platzhalter verwenden.

Flight::route('/blog/*', function () {
  // Dies passt zu /blog/2000/02/01
});

Um alle Anforderungen an einen einzelnen Rückruf zu leiten, können Sie Folgendes tun:

Flight::route('*', function () {
  // Mach etwas
});

Weiterleitung

Sie können die Ausführung an die nächste übereinstimmende Route weiterleiten, indem Sie true aus Ihrer Rückruffunktion zurückgeben.

Flight::route('/benutzer/@name', function (string $name) {
  // Eine Bedingung prüfen
  if ($name !== "Bob") {
    // Zu nächster Route fortsetzen
    return true;
  }
});

Flight::route('/benutzer/*', function () {
  // Dies wird aufgerufen
});

Routenalias

Sie können einem Routen einen Alias zuweisen, damit die URL später in Ihrem Code dynamisch generiert werden kann (z. B. in einer Vorlage).

Flight::route('/benutzer/@id', function($id) { echo 'Benutzer:'.$id; }, false, 'benutzer_ansehen');

// später im Code irgendwo
Flight::getUrl('benutzer_ansehen', [ 'id' => 5 ]); // gibt '/benutzer/5' zurück

Dies ist besonders hilfreich, wenn sich Ihre URL ändern sollte. Im obigen Beispiel, nehmen wir an, dass Benutzer zu /admin/benutzer/@id verschoben wurde. Mit Aliasbildung müssen Sie nirgendwo, wo Sie auf den Alias verweisen, etwas ändern, da der Alias jetzt /admin/benutzer/5 wie im obigen Beispiel zurückgeben wird.

Routenaliasierung funktioniert auch in Gruppen:

Flight::group('/benutzer', function() {
    Flight::route('/@id', function($id) { echo 'Benutzer:'.$id; }, false, 'benutzer_ansehen');
});

// später im Code irgendwo
Flight::getUrl('benutzer_ansehen', [ 'id' => 5 ]); // gibt '/benutzer/5' zurück

Routeninformationen

Wenn Sie die übereinstimmenden Routeninformationen inspizieren möchten, können Sie die Routen Objekt anfordern, das an Ihre Rückruffunktion übergeben werden soll, indem Sie true als dritten Parameter in dem Routenmethode. Das Routenobjekt wird immer der letzte Parameter sein, der an Ihre Rückruffunktion übergeben wird.

Flight::route('/', function(\flight\net\Route $route) {
  // Array der HTTP-Methoden, die abgeglichen sind
  $route->methods;

  // Array der benannten Parameter
  $route->params;

  // Übereinstimmender regulärer Ausdruck
  $route->regex;

  // Enthält den Inhalt von * in dem URL-Muster
  $route->splat;

  // Zeigt den URL-Pfad an....wenn Sie dies wirklich benötigen
  $route->pattern;

  // Zeigt an, welches Middleware dieser Route zugewiesen ist
  $route->middleware;

  // Zeigt den diesem Routen zugewiesenen Alias an
  $route->alias;
}, true);

Routengruppierung

Es kann Zeiten geben, in denen Sie verwandte Routen zusammenfassen möchten (z. B. /api/v1). Sie können dies durch Verwendung der group Methode tun:

Flight::group('/api/v1', function () {
  Flight::route('/benutzer', function () {
    // Passt zu /api/v1/benutzer
  });

  Flight::route('/posten', function () {
    // Passt zu /api/v1/posten
  });
});

Sie können sogar Gruppen von Gruppen verschachteln:

Flight::group('/api', function () {
  Flight::group('/v1', function () {
    // Flight::get() ruft Variablen ab, setzt jedoch keine Route! Siehe Objektkontext unten
    Flight::route('GET /benutzer', function () {
      // Passt zu GET /api/v1/benutzer
    });

    Flight::post('/posten', function () {
      // Passt zu POST /api/v1/posten
    });

    Flight::put('/posten/1', function () {
      // Passt zu PUT /api/v1/posten
    });
  });
  Flight::group('/v2', function () {

    // Flight::get() ruft Variablen ab, setzt jedoch keine Route! Siehe Objektkontext unten
    Flight::route('GET /benutzer', function () {
      // Passt zu GET /api/v2/benutzer
    });
  });
});

Gruppierung mit Objektkontext

Sie können weiterhin Routengruppierung mit dem Engine-Objekt auf die folgende Weise verwenden:

$app = new \flight\Engine();
$app->group('/api/v1', function (Router $router) {

  // Verwenden Sie die $router Variable
  $router->get('/benutzer', function () {
    // Passt zu GET /api/v1/benutzer
  });

  $router->post('/posten', function () {
    // Passt zu POST /api/v1/posten
  });
});

Streamen

Sie können jetzt Antworten an den Client streamen, indem Sie die streamWithHeaders()-Methode verwenden. Dies ist nützlich zum Senden großer Dateien, länger laufender Prozesse oder zur Erzeugung großer Antworten. Das Streamen einer Route wird etwas anders behandelt als eine reguläre Route.

Hinweis: Das Streamen von Antworten ist nur verfügbar, wenn Sie flight.v2.output_buffering auf false gesetzt haben.

Flight::route('/benutzer-streamen', function() {

    // Wenn Sie hier nach Ausführung der Route zusätzliche Header setzen müssen
    // müssen Sie sie definieren, bevor irgendetwas ausgegeben wird.
    // Sie müssen alle ein direkter Aufruf der header() Funktion oder
    // ein Aufruf von Flight::response()->setRealHeader()
    header('Content-Disposition: attachment; filename="benutzer.json"');
    // oder
    Flight::response()->setRealHeader('Content-Disposition', 'attachment; filename="benutzer.json"');

    // wie auch immer Sie Ihre Daten abrufen, nur als Beispiel...
    $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users");

    echo '{';
    $user_count = count($users);
    while($user = $users_stmt->fetch(PDO::FETCH_ASSOC)) {
        echo json_encode($user);
        if(--$user_count > 0) {
            echo ',';
        }

        // Dies ist erforderlich, um die Daten an den Client zu senden
        ob_flush();
    }
    echo '}';

// So setzen Sie die Header, bevor Sie mit dem Streamen beginnen.
})->streamWithHeaders([
    'Content-Type' => 'application/json',
    // optionaler Statuscode, Standard: 200
    'status' => 200
]);

Learn/variables

Variablen

Flight ermöglicht es Ihnen, Variablen zu speichern, damit sie überall in Ihrer Anwendung verwendet werden können.

// Speichern Sie Ihre Variable
Flight::set('id', 123);

// Anderswo in Ihrer Anwendung
$id = Flight::get('id');

Um zu überprüfen, ob eine Variable festgelegt wurde, können Sie Folgendes tun:

if (Flight::has('id')) {
  // Mach etwas
}

Sie können eine Variable löschen, indem Sie Folgendes tun:

// Löscht die id-Variable
Flight::clear('id');

// Löscht alle Variablen
Flight::clear();

Flight verwendet auch Variablen für Konfigurationszwecke.

Flight::set('flight.log_errors', true);

Learn/dependency_injection_container

Dependency Injection Container

Einführung

Der Dependency Injection Container (DIC) ist ein leistungsstolles Werkzeug, das es Ihnen ermöglicht, die Abhängigkeiten Ihrer Anwendung zu verwalten. Es handelt sich um ein Schlüsselkonzept in modernen PHP-Frameworks und wird zur Verwaltung der Instanziierung und Konfiguration von Objekten verwendet. Einige Beispiele für DIC-Bibliotheken sind: Dice, Pimple, PHP-DI und league/container.

Ein DIC ist eine elegante Möglichkeit zu sagen, dass es Ihnen ermöglicht, Ihre Klassen an einem zentralen Ort zu erstellen und zu verwalten. Dies ist nützlich, wenn Sie dasselbe Objekt an mehrere Klassen (wie Ihre Controller) übergeben müssen. Ein einfaches Beispiel könnte dabei helfen, dies verständlicher zu machen.

Grundlegendes Beispiel

Der alte Weg, Dinge zu erledigen, könnte wie folgt aussehen:


require 'vendor/autoload.php';

// Klasse zur Verwaltung von Benutzern aus der Datenbank
class UserController {

    protected PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function view(int $id) {
        $stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
        $stmt->execute(['id' => $id]);

        print_r($stmt->fetch());
    }
}

$User = new UserController(new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'));
Flight::route('/user/@id', [ $UserController, 'view' ]);

Flight::start();

Man kann aus dem obigen Code erkennen, dass wir ein neues PDO-Objekt erstellen und es unserer UserController-Klasse übergeben. Dies ist für eine kleine Anwendung in Ordnung, aber wenn Ihre Anwendung wächst, werden Sie feststellen, dass Sie das gleiche PDO-Objekt an mehreren Stellen erstellen. Hier kommt ein DIC zum Einsatz.

Hier ist dasselbe Beispiel unter Verwendung eines DIC (mit Dice):


require 'vendor/autoload.php';

// dieselbe Klasse wie oben. Nichts geändert
class UserController {

    protected PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function view(int $id) {
        $stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
        $stmt->execute(['id' => $id]);

        print_r($stmt->fetch());
    }
}

// einen neuen Container erstellen
$container = new \Dice\Dice;
// vergessen Sie nicht, es wie unten sich selbst neu zuzuweisen!
$container = $container->addRule('PDO', [
    // shared bedeutet, dass jedes Mal dasselbe Objekt zurückgegeben wird
    'shared' => true,
    'constructParams' => ['mysql:host=localhost;dbname=test', 'user', 'pass' ]
]);

// Hiermit wird der Container Handler registriert, sodass Flight weiß, dass er ihn verwenden soll.
Flight::registerContainerHandler(function($class, $params) use ($container) {
    return $container->create($class, $params);
});

// Jetzt können wir den Container verwenden, um unseren UserController zu erstellen
Flight::route('/user/@id', [ 'UserController', 'view' ]);
// oder alternativ können Sie die Route wie folgt definieren
Flight::route('/user/@id', 'UserController->view');
// oder
Flight::route('/user/@id', 'UserController::view');

Flight::start();

Ich wette, Sie denken, es wurde viel zusätzlicher Code zum Beispiel hinzugefügt. Die Magie entsteht, wenn Sie einen weiteren Controller haben, der das PDO-Objekt benötigt.


// Wenn all Ihre Controller einen Konstruktor haben, der ein PDO-Objekt benötigt
// werden jedem der unten stehenden Routen automatisch injiziert!!!
Flight::route('/unternehmen/@id', 'Unternehmenscontroller->view');
Flight::route('/organisation/@id', 'Organisationscontroller->view');
Flight::route('/kategorie/@id', 'Kategoriescontroller->view');
Flight::route('/einstellungen', 'Einstellungscontroller->view');

Der zusätzliche Bonus bei der Verwendung eines DIC ist, dass das Unit Testing deutlich einfacher wird. Sie können ein Mock-Objekt erstellen und es Ihrer Klasse übergeben. Das ist ein großer Vorteil, wenn Sie Tests für Ihre Anwendung schreiben!

PSR-11

Flight kann auch jeden Container verwenden, der mit PSR-11 kompatibel ist. Dies bedeutet, dass Sie jeden Container verwenden können, der das PSR-11-Interface implementiert. Hier ist ein Beispiel unter Verwendung des PSR-11-Containers von League:


require 'vendor/autoload.php';

// dieselbe UserController-Klasse wie oben

$container = new \League\Container\Container();
$container->add(UserController::class)->addArgument(PdoWrapper::class);
$container->add(PdoWrapper::class)
    ->addArgument('mysql:host=localhost;dbname=test')
    ->addArgument('user')
    ->addArgument('pass');
Flight::registerContainerHandler($container);

Flight::route('/benutzer', [ 'Benutzercontroller', 'view' ]);

Flight::start();

Dies kann etwas ausführlicher sein als das vorherige Dice-Beispiel, erledigt jedoch die gleiche Arbeit mit den gleichen Vorteilen!

Eigener DIC-Handler

Sie können auch Ihren eigenen DIC-Handler erstellen. Dies ist nützlich, wenn Sie einen benutzerdefinierten Container verwenden möchten, der nicht PSR-11-konform ist (Dice). Sehen Sie sich das Grundbeispiel an, um herauszufinden, wie dies funktioniert.

Zusätzlich gibt es einige hilfreiche Standards, die Ihr Leben erleichtern, wenn Sie Flight verwenden.

Engine-Instanz

Wenn Sie die Engine-Instanz in Ihren Controllern/Middleware verwenden, erhalten Sie hier die Konfiguration:


// Irgendwo in Ihrer Startdatei
$engine = Flight::app();

$container = new \Dice\Dice;
$container = $container->addRule('*', [
    'substitutions' => [
        // Hier übergeben Sie die Instanz
        Engine::class => $engine
    ]
]);

$engine->registerContainerHandler(function($class, $params) use ($container) {
    return $container->create($class, $params);
});

// Jetzt können Sie die Engine-Instanz in Ihren Controllern/Middleware verwenden

class MeinController {
    public function __construct(Engine $app) {
        $this->app = $app;
    }

    public function index() {
        $this->app->render('index');
    }
}

Hinzufügen weiterer Klassen

Wenn Sie andere Klassen dem Container hinzufügen möchten, ist dies mit Dice einfach, da sie automatisch vom Container aufgelöst werden. Hier ist ein Beispiel:


$container = new \Dice\Dice;
// Wenn Sie nichts in Ihre Klasse einspeisen müssen
// müssen Sie nichts definieren!
Flight::registerContainerHandler(function($class, $params) use ($container) {
    return $container->create($class, $params);
});

class MeineBenutzerdefinierteKlasse {
    public function analyseThing() {
        return 'Sache';
    }
}

class Benutzercontroller {

    protected MyCustomClass $MyCustomClass;

    public function __construct(MyCustomClass $MyCustomClass) {
        $this->MyCustomClass = $MyCustomClass;
    }

    public function index() {
        echo $this->MyCustomClass->parseThing();
    }
}

Flight::route('/benutzer', 'Benutzercontroller->index');

Learn/middleware

Routen Middleware

Flight unterstützt Routen- und Gruppenrouten-Middleware. Middleware ist eine Funktion, die vor (oder nach) dem Routen-Callback ausgeführt wird. Dies ist eine großartige Möglichkeit, API-Authentifizierungsprüfungen in Ihrem Code hinzuzufügen oder zu überprüfen, ob der Benutzer die Berechtigung zum Zugriff auf die Route hat.

Basis-Middleware

Hier ist ein grundlegendes Beispiel:

// Wenn Sie nur eine anonyme Funktion bereitstellen, wird sie vor dem Routen-Callback ausgeführt.
// Es gibt keine "nach"-Middleware-Funktionen außer Klassen (siehe unten)
Flight::route('/pfad', function() { echo 'Hier bin ich!'; })->addMiddleware(function() {
    echo 'Middleware zuerst!';
});

Flight::start();

// Dies gibt "Middleware zuerst! Hier bin ich!" aus

Es gibt einige sehr wichtige Hinweise zur Middleware, die Sie kennen sollten, bevor Sie sie verwenden:

Middleware-Klassen

Middleware kann auch als Klasse registriert werden. Wenn Sie die "nach"-Funktionalität benötigen, müssen Sie eine Klasse verwenden.

class MyMiddleware {
    public function before($params) {
        echo 'Middleware zuerst!';
    }

    public function after($params) {
        echo 'Middleware zuletzt!';
    }
}

$MyMiddleware = new MyMiddleware();
Flight::route('/pfad', function() { echo 'Hier bin ich! '; })->addMiddleware($MyMiddleware); // auch ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]);

Flight::start();

// Dies zeigt "Middleware zuerst! Hier bin ich! Middleware zuletzt!" an

Gruppierung von Middleware

Sie können eine Routengruppe hinzufügen, und dann wird jede Route in dieser Gruppe auch die gleiche Middleware haben. Dies ist nützlich, wenn Sie z. B. eine Auth-Middleware benötigen, um den API-Schlüssel im Header zu überprüfen.


// am Ende der Gruppenmethode hinzugefügt
Flight::group('/api', function() {

    // Diese "leer" aussehende Route wird tatsächlich mit /api übereinstimmen
    Flight::route('', function() { echo 'api'; }, false, 'api');
    Flight::route('/benutzer', function() { echo 'benutzer'; }, false, 'benutzer');
    Flight::route('/benutzer/@id', function($id) { echo 'benutzer:'.$id; }, false, 'benutzer_anzeigen');
}, [ new ApiAuthMiddleware() ]);

Wenn Sie eine globale Middleware auf alle Ihre Routen anwenden möchten, können Sie eine "leere" Gruppe hinzufügen:


// am Ende der Gruppenmethode hinzugefügt
Flight::group('', function() {
    Flight::route('/benutzer', function() { echo 'benutzer'; }, false, 'benutzer');
    Flight::route('/benutzer/@id', function($id) { echo 'benutzer:'.$id; }, false, 'benutzer_anzeigen');
}, [ new ApiAuthMiddleware() ]);

Learn/filtering

Filtern

Flight ermöglicht es Ihnen, Methoden vor und nach ihrem Aufruf zu filtern. Es gibt keine vordefinierten Hooks, die Sie sich merken müssen. Sie können beliebige der Standardframework-Methoden sowie benutzerdefinierte Methoden filtern, die Sie zugeordnet haben.

Eine Filterfunktion sieht so aus:

function (array &$params, string &$output): bool {
  // Filtercode
}

Unter Verwendung der übergebenen Variablen können Sie die Eingabeparameter und/oder die Ausgabe manipulieren.

Sie können einen Filter vor einer Methode ausführen, indem Sie dies tun:

Flight::before('start', function (array &$params, string &$output): bool {
  // Etwas machen
});

Sie können einen Filter nach einer Methode ausführen, indem Sie dies tun:

Flight::after('start', function (array &$params, string &$output): bool {
  // Etwas machen
});

Sie können beliebig viele Filter zu einer Methode hinzufügen. Sie werden in der Reihenfolge aufgerufen, in der sie deklariert sind.

Hier ist ein Beispiel des Filtervorgangs:

// Eine benutzerdefinierte Methode zuordnen
Flight::map('hallo', function (string $name) {
  return "Hallo, $name!";
});

// Einen Vorfiler hinzufügen
Flight::before('hallo', function (array &$params, string &$output): bool {
  // Den Parameter manipulieren
  $params[0] = 'Fred';
  return true;
});

// Einen Nachfilter hinzufügen
Flight::after('hallo', function (array &$params, string &$output): bool {
  // Die Ausgabe manipulieren
  $output .= " Einen schönen Tag!";
  return true;
});

// Die benutzerdefinierte Methode aufrufen
echo Flight::hallo('Bob');

Dies sollte anzeigen:

Hallo Fred! Einen schönen Tag!

Wenn Sie mehrere Filter definiert haben, können Sie die Kette unterbrechen, indem Sie in einer Ihrer Filterfunktionen false zurückgeben:

Flight::before('start', function (array &$params, string &$output): bool {
  echo 'eins';
  return true;
});

Flight::before('start', function (array &$params, string &$output): bool {
  echo 'zwei';

  // Dies wird die Kette beenden
  return false;
});

// Dies wird nicht aufgerufen
Flight::before('start', function (array &$params, string &$output): bool {
  echo 'drei';
  return true;
});

Hinweis: Kernmethoden wie map und register können nicht gefiltert werden, da sie direkt aufgerufen und nicht dynamisch aufgerufen werden.

Learn/requests

Anfragen

Flight kapselt die HTTP-Anfrage in ein einzelnes Objekt, auf das zugegriffen werden kann, indem Folgendes getan wird:

$request = Flight::request();

Das Anfrageobjekt stellt die folgenden Eigenschaften bereit:

Sie können auf die Eigenschaften query, data, cookies und files als Arrays oder Objekte zugreifen.

Um beispielsweise einen Abfragezeichenfolgenparameter zu erhalten, können Sie Folgendes tun:

$id = Flight::request()->query['id'];

Oder Sie können Folgendes tun:

$id = Flight::request()->query->id;

ROHER Anfragekörper

Um den Roh-HTTP-Anfragekörper zu erhalten, beispielsweise beim Umgang mit PUT-Anfragen, können Sie Folgendes tun:

$body = Flight::request()->getBody();

JSON-Eingabe

Wenn Sie eine Anfrage mit dem Typ application/json und den Daten {"id": 123} senden, sind diese über die data-Eigenschaft verfügbar:

$id = Flight::request()->data->id;

Zugriff auf $_SERVER

Es gibt eine Abkürzung zum Zugriff auf das Array $_SERVER über die Methode getVar():


$host = Flight::request()->getVar['HTTP_HOST'];

Zugriff auf Anfrageheader

Sie können auf Anfrageheader mit der Methode getHeader() oder getHeaders() zugreifen:


// Möglicherweise benötigen Sie den Autorisierungsheader
$host = Flight::request()->getHeader('Authorization');

// Wenn Sie alle Header abrufen müssen
$headers = Flight::request()->getHeaders();

Learn/frameworkmethods

Methoden des Frameworks

Flight wurde entwickelt, um einfach zu bedienen und zu verstehen zu sein. Im Folgenden finden Sie die vollständige Liste der Methoden für das Framework. Es besteht aus Kernmethoden, die reguläre statische Methoden sind, und erweiterbaren Methoden, die zugeordnete Methoden sind, die gefiltert oder überschrieben werden können.

Kernmethoden

Flight::map(string $name, callable $callback, bool $pass_route = false) // Erstellt eine benutzerdefinierte Framework-Methode.
Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Registriert eine Klasse bei einer Framework-Methode.
Flight::before(string $name, callable $callback) // Fügt einen Filter vor einer Framework-Methode hinzu.
Flight::after(string $name, callable $callback) // Fügt einen Filter nach einer Framework-Methode hinzu.
Flight::path(string $path) // Fügt einen Pfad zum Laden von Klassen hinzu.
Flight::get(string $key) // Ruft eine Variable ab.
Flight::set(string $key, mixed $value) // Legt eine Variable fest.
Flight::has(string $key) // Überprüft, ob eine Variable festgelegt ist.
Flight::clear(array|string $key = []) // Löscht eine Variable.
Flight::init() // Initialisiert das Framework auf die Standardeinstellungen.
Flight::app() // Ruft die Anwendungsobjektinstanz ab.

Erweiterbare Methoden

Flight::start() // Startet das Framework.
Flight::stop() // Stoppt das Framework und sendet eine Antwort.
Flight::halt(int $code = 200, string $message = '') // Stoppt das Framework mit einem optionalen Statuscode und einer Nachricht.
Flight::route(string $pattern, callable $callback, bool $pass_route = false) // Ordnet ein URL-Muster einer Rückruffunktion zu.
Flight::group(string $pattern, callable $callback) // Erstellt Gruppierung für URLs, Muster muss ein String sein.
Flight::redirect(string $url, int $code) // Leitet zu einer anderen URL um.
Flight::render(string $file, array $data, ?string $key = null) // Rendert eine Vorlagendatei.
Flight::error(Throwable $error) // Sendet eine HTTP 500-Antwort.
Flight::notFound() // Sendet eine HTTP 404-Antwort.
Flight::etag(string $id, string $type = 'string') // Führt ETag-HTTP-Caching durch.
Flight::lastModified(int $time) // Führt HTTP-Caching für zuletzt geändert durch.
Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sendet eine JSON-Antwort.
Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sendet eine JSONP-Antwort.

Alle benutzerdefinierten Methoden, die mit map und register hinzugefügt wurden, können auch gefiltert werden.

Learn/api

Methoden der Framework-API

Flight wurde entwickelt, um einfach zu bedienen und zu verstehen zu sein. Hier ist die vollständige Liste der Methoden für das Framework. Diese besteht aus Kernmethoden, die reguläre statische Methoden sind, und erweiterbaren Methoden, die zugeordnete Methoden sind, die gefiltert oder überschrieben werden können.

Kernmethoden

Diese Methoden sind wesentlich für das Framework und können nicht überschrieben werden.

Flight::map(string $name, callable $callback, bool $pass_route = false) // Erstellt eine benutzerdefinierte Framework-Methode.
Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Registriert eine Klasse bei einer Framework-Methode.
Flight::unregister(string $name) // Entfernt eine Klasse von einer Framework-Methode.
Flight::before(string $name, callable $callback) // Fügt einen Filter vor einer Framework-Methode hinzu.
Flight::after(string $name, callable $callback) // Fügt einen Filter nach einer Framework-Methode hinzu.
Flight::path(string $path) // Fügt einen Pfad zum Laden von Klassen hinzu.
Flight::get(string $key) // Ruft eine Variable ab.
Flight::set(string $key, mixed $value) // Legt eine Variable fest.
Flight::has(string $key) // Überprüft, ob eine Variable festgelegt ist.
Flight::clear(array|string $key = []) // Löscht eine Variable.
Flight::init() // Initialisiert das Framework auf seine Standardwerte.
Flight::app() // Ruft die Objektinstanz der Anwendung ab
Flight::request() // Ruft die Objektinstanz der Anfrage ab
Flight::response() // Ruft die Objektinstanz der Antwort ab
Flight::router() // Ruft die Objektinstanz des Routers ab
Flight::view() // Ruft die Objektinstanz der Ansicht ab

Erweiterbare Methoden

Flight::start() // Startet das Framework.
Flight::stop() // Stoppt das Framework und sendet eine Antwort.
Flight::halt(int $code = 200, string $message = '') // Stoppt das Framework mit optionalen Statuscode und Nachricht.
Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Ordnet ein URL-Muster einer Rückruffunktion zu.
Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Ordnet ein URL-Muster für POST-Anfragen einer Rückruffunktion zu.
Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Ordnet ein URL-Muster für PUT-Anfragen einer Rückruffunktion zu.
Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Ordnet ein URL-Muster für PATCH-Anfragen einer Rückruffunktion zu.
Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Ordnet ein URL-Muster für DELETE-Anfragen einer Rückruffunktion zu.
Flight::group(string $pattern, callable $callback) // Erstellt Gruppierungen für URLs, Muster muss ein String sein.
Flight::getUrl(string $name, array $params = []) // Generiert eine URL basierend auf einem Routen-Alias.
Flight::redirect(string $url, int $code) // Leitet zu einer anderen URL weiter.
Flight::render(string $file, array $data, ?string $key = null) // Rendert eine Vorlagendatei.
Flight::error(Throwable $error) // Sendet eine HTTP 500 Antwort.
Flight::notFound() // Sendet eine HTTP 404 Antwort.
Flight::etag(string $id, string $type = 'string') // Führt ETag-HTTP-Caching durch.
Flight::lastModified(int $time) // Führt HTTP-Caching für zuletzt geändert durch.
Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sendet eine JSON-Antwort.
Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Sendet eine JSONP-Antwort.

Alle benutzerdefinierten Methoden, die mit map und register hinzugefügt wurden, können auch gefiltert werden.

Learn/why_frameworks

Warum ein Framework?

Einige Programmierer sind vehement gegen die Verwendung von Frameworks. Sie argumentieren, dass Frameworks überladen, langsam und schwer zu erlernen sind. Sie sagen, dass Frameworks unnötig sind und dass man besseren Code ohne sie schreiben kann. Es gibt sicherlich einige gültige Punkte bezüglich der Nachteile der Verwendung von Frameworks. Allerdings gibt es auch viele Vorteile bei der Verwendung von Frameworks.

Gründe für die Verwendung eines Frameworks

Hier sind ein paar Gründe, warum Sie möglicherweise in Betracht ziehen möchten, ein Framework zu verwenden:

Flight ist ein Mikro-Framework. Das bedeutet, dass es klein und leicht ist. Es bietet nicht so viele Funktionen wie größere Frameworks wie Laravel oder Symfony. Es bietet jedoch viele der Funktionen, die Sie benötigen, um Webanwendungen zu erstellen. Es ist auch einfach zu lernen und zu verwenden. Dies macht es zu einer guten Wahl für den schnellen und einfachen Aufbau von Webanwendungen. Wenn Sie neu in der Verwendung von Frameworks sind, ist Flight ein großartiges Anfänger-Framework, mit dem Sie beginnen können. Es wird Ihnen helfen, die Vorteile der Verwendung von Frameworks kennenzulernen, ohne Sie mit zu viel Komplexität zu überfordern. Nachdem Sie etwas Erfahrung mit Flight gesammelt haben, wird es einfacher sein, auf komplexere Frameworks wie Laravel oder Symfony zu wechseln. Allerdings kann Flight immer noch eine erfolgreiche robuste Anwendung erstellen.

Was ist Routing?

Routing ist der Kern des Flight-Frameworks, aber was ist es genau? Routing ist der Prozess, eine URL zu nehmen und sie mit einer bestimmten Funktion in Ihrem Code abzugleichen. So können Sie Ihre Website basierend auf der angeforderten URL unterschiedliche Dinge tun lassen. Zum Beispiel möchten Sie möglicherweise das Profil eines Benutzers anzeigen, wenn er /benutzer/1234 besucht, oder eine Liste aller Benutzer anzeigen, wenn er /benutzer besucht. All dies geschieht über Routing.

Es könnte so funktionieren:

Und warum ist das wichtig?

Ein ordnungsgemäß zentralisierter Router kann Ihr Leben tatsächlich erheblich erleichtern! Es könnte nur schwer zu erkennen sein, wenn Sie zuerst darauf schauen. Hier sind ein paar Gründe, warum:

Ich bin sicher, dass Ihnen der Skript-für-Skript-Weg, eine Website zu erstellen, vertraut ist. Sie könnten eine Datei namens index.php haben, die eine Menge if-Anweisungen enthält, um die URL zu überprüfen und dann basierend auf der URL eine bestimmte Funktion auszuführen. Dies ist eine Form des Routings, aber es ist nicht sehr organisiert und kann schnell außer Kontrolle geraten. Das Routing-System von Flight ist eine viel organisiertere und leistungsstärkere Methode, um das Routing zu handhaben.

Das?


// /benutzer/profil_anzeigen.php?id=1234
if ($_GET['id']) {
    $id = $_GET['id'];
    BenutzerprofilAnzeigen($id);
}

// /benutzer/profil_bearbeiten.php?id=1234
if ($_GET['id']) {
    $id = $_GET['id'];
    BenutzerprofilBearbeiten($id);
}

// usw...

Oder das?


// index.php
Flight::route('/benutzer/@id', [ 'BenutzerController', 'BenutzerprofilAnzeigen' ]);
Flight::route('/benutzer/@id/bearbeiten', [ 'BenutzerController', 'BenutzerprofilBearbeiten' ]);

// Vielleicht in Ihrem app/controllers/BenutzerController.php
class BenutzerController {
    public function BenutzerprofilAnzeigen($id) {
        // etwas tun
    }

    public function BenutzerprofilBearbeiten($id) {
        // etwas tun
    }
}

Hoffentlich können Sie langsam beginnen, die Vorteile der Verwendung eines zentralisierten Routing-Systems zu erkennen. Es ist viel einfacher zu verwalten und zu verstehen auf lange Sicht!

Anfragen und Antworten

Flight bietet eine einfache und effektive Möglichkeit, Anfragen und Antworten zu handhaben. Dies ist der Kern dessen, was ein Web-Framework tut. Es nimmt eine Anfrage vom Browser eines Benutzers entgegen, verarbeitet sie und sendet dann eine Antwort zurück. So können Sie Webanwendungen erstellen, die Dinge wie das Anzeigen des Profils eines Benutzers, das Einloggen eines Benutzers oder das Verfassen eines neuen Blog-Beitrags ermöglichen.

Anfragen

Eine Anfrage ist das, was der Browser eines Benutzers an Ihren Server sendet, wenn er Ihre Website besucht. Diese Anfrage enthält Informationen darüber, was der Benutzer tun möchte. Sie könnte beispielsweise Informationen darüber enthalten, welche URL der Benutzer besuchen möchte, welche Daten der Benutzer an Ihren Server senden möchte oder welche Art von Daten der Benutzer von Ihrem Server erhalten möchte. Es ist wichtig zu wissen, dass eine Anfrage schreibgeschützt ist. Sie können die Anfrage nicht ändern, aber Sie können daraus lesen.

Flight bietet einen einfachen Weg, um Informationen über die Anfrage abzurufen. Sie können Informationen über die Anfrage mithilfe der Flight::request()-Methode abrufen. Diese Methode gibt ein Request-Objekt zurück, das Informationen über die Anfrage enthält. Sie können dieses Objekt verwenden, um Informationen über die Anfrage abzurufen, wie z. B. die URL, die Methode oder die Daten, die der Benutzer an Ihren Server gesendet hat.

Antworten

Eine Antwort ist das, was Ihr Server zurück an den Browser des Benutzers sendet, wenn er Ihre Website besucht. Diese Antwort enthält Informationen darüber, was Ihr Server tun möchte. Sie könnte beispielsweise Informationen darüber enthalten, welche Art von Daten Ihr Server an den Benutzer senden möchte, welche Art von Daten Ihr Server vom Benutzer erhalten möchte oder welche Art von Daten Ihr Server auf dem Computer des Benutzers speichern möchte.

Flight bietet einen einfachen Weg, um eine Antwort an den Browser eines Benutzers zu senden. Sie können eine Antwort mit der Flight::response()-Methode senden. Diese Methode akzeptiert ein Response-Objekt als Argument und sendet die Antwort an den Browser des Benutzers. Sie können dieses Objekt verwenden, um eine Antwort an den Browser des Benutzers zu senden, wie z. B. HTML, JSON oder eine Datei. Flight hilft Ihnen dabei, einige Teile der Antwort automatisch zu generieren, um die Dinge zu vereinfachen, aber letztendlich haben Sie die Kontrolle darüber, was Sie dem Benutzer zurückschicken.

Learn/httpcaching

HTTP-Caching

Flight stellt eine eingebaute Unterstützung für das Caching auf HTTP-Ebene bereit. Wenn die Cache-Bedingung erfüllt ist, wird Flight eine HTTP 304 Not Modified-Antwort zurückgeben. Das nächste Mal, wenn der Client die gleiche Ressource anfordert, wird er aufgefordert, die lokal zwischengespeicherte Version zu verwenden.

Zuletzt geändert

Sie können die lastModified-Methode verwenden und einen UNIX-Zeitstempel übergeben, um das Datum und die Uhrzeit festzulegen, wann eine Seite zuletzt geändert wurde. Der Client wird weiterhin seinen Cache verwenden, bis der zuletzt geänderte Wert geändert wird.

Flight::route('/nachrichten', function () {
  Flight::lastModified(1234567890);
  echo 'Dieser Inhalt wird zwischengespeichert sein.';
});

ETag

Das Caching von ETag ist ähnlich wie Last-Modified, außer dass Sie eine beliebige ID für die Ressource angeben können:

Flight::route('/nachrichten', function () {
  Flight::etag('meine-eindeutige-id');
  echo 'Dieser Inhalt wird zwischengespeichert sein.';
});

Denken Sie daran, dass das Aufrufen von lastModified oder etag sowohl den Cache-Wert setzen als auch überprüfen wird. Wenn der Cache-Wert zwischen den Anfragen identisch ist, sendet Flight sofort eine HTTP 304-Antwort und stoppt die Verarbeitung.

Learn/responses

Antworten

Flight helft dabei, einen Teil der Antwortheader für Sie zu generieren, aber Sie haben die meiste Kontrolle darüber, was Sie an den Benutzer zurücksenden. Manchmal können Sie direkt auf das Response-Objekt zugreifen, aber meistens verwenden Sie die Flight-Instanz, um eine Antwort zu senden.

Senden einer einfachen Antwort

Flight verwendet ob_start(), um die Ausgabe zu puffern. Das bedeutet, dass Sie echo oder print verwenden können, um eine Antwort an den Benutzer zu senden, und Flight wird sie erfassen und mit den entsprechenden Headern an den Benutzer zurücksenden.


// Dies sendet "Hallo, Welt!" an den Browser des Benutzers
Flight::route('/', function() {
    echo "Hallo, Welt!";
});

// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Hallo, Welt!

Alternativ können Sie die Methode write() aufrufen, um den Inhalt des Body zu ergänzen.


// Dies sendet "Hallo, Welt!" an den Browser des Benutzers
Flight::route('/', function() {
    // ausführlich, aber manchmal erforderlich, wenn Sie es brauchen
    Flight::response()->write("Hallo, Welt!");

    // wenn Sie den Body abrufen möchten, den Sie zu diesem Zeitpunkt festgelegt haben
    // können Sie dies wie folgt tun
    $body = Flight::response()->getBody();
});

Statuscodes

Sie können den Statuscode der Antwort mit der Methode status festlegen:

Flight::route('/@id', function($id) {
    if($id == 123) {
        Flight::response()->status(200);
        echo "Hallo, Welt!";
    } else {
        Flight::response()->status(403);
        echo "Verboten";
    }
});

Wenn Sie den aktuellen Statuscode abrufen möchten, können Sie die Methode status ohne Argumente verwenden:

Flight::response()->status(); // 200

Festlegen eines Antwort-Headers

Sie können einen Header wie den Inhalts-Typ der Antwort festlegen, indem Sie die Methode header verwenden:


// Dies sendet "Hallo, Welt!" im Klartext an den Browser des Benutzers
Flight::route('/', function() {
    Flight::response()->header('Content-Type', 'text/plain');
    echo "Hallo, Welt!";
});

JSON

Flight bietet Unterstützung zum Senden von JSON- und JSONP-Antworten. Um eine JSON-Antwort zu senden, übergeben Sie einige Daten, die in JSON codiert werden sollen:

Flight::json(['id' => 123]);

JSONP

Für JSONP-Anfragen können Sie optional den Abfrageparameter angeben, den Sie verwenden, um Ihre Callback-Funktion zu definieren:

Flight::jsonp(['id' => 123], 'q');

Wenn Sie eine GET-Anforderung mit ?q=my_func senden, sollten Sie die Ausgabe erhalten:

my_func({"id":123});

Wenn Sie keinen Abfrageparameter angeben, wird standardmäßig jsonp verwendet.

Umleiten zu einer anderen URL

Sie können die aktuelle Anforderung mit der Methode redirect() umleiten, indem Sie eine neue URL angeben:

Flight::redirect('/neuer/ort');

Standardmäßig sendet Flight einen HTTP-Statuscode 303 ("Siehe Andere"). Sie können optional einen benutzerdefinierten Code festlegen:

Flight::redirect('/neuer/ort', 401);

Stoppen

Sie können das Framework jederzeit anhalten, indem Sie die Methode halt aufrufen:

Flight::halt();

Sie können auch optional einen HTTP-Statuscode und eine Nachricht angeben:

Flight::halt(200, 'Bin gleich zurück...');

Ein Aufruf von halt verwirft jeglichen Antwortinhalt bis zu diesem Zeitpunkt. Wenn Sie das Framework stoppen und die aktuelle Antwort ausgeben möchten, verwenden Sie die Methode stop:

Flight::stop();

HTTP-Caching

Flight bietet integrierte Unterstützung für Caching auf HTTP-Ebene. Wenn die Caching-Bedingung erfüllt ist, sendet Flight eine HTTP 304 Not Modified-Antwort zurück. Wenn der Client das nächste Mal auf die gleiche Ressource zugreift, wird er aufgefordert, seine lokal zwischengespeicherte Version zu verwenden.

Caching auf Routenebene

Wenn Sie Ihre gesamte Antwort zwischenspeichern möchten, können Sie die cache()-Methode verwenden und die Zwischenspeicherungszeit angeben.


// Dies zwischenspeichert die Antwort für 5 Minuten
Flight::route('/nachrichten', function () {
  Flight::response()->cache(time() + 300);
  echo 'Dieser Inhalt wird zwischengespeichert.';
});

// Alternativ können Sie einen String verwenden, den Sie an die strtotime() Methode übergeben würden
Flight::route('/nachrichten', function () {
  Flight::cache('+5 Minuten');
  echo 'Dieser Inhalt wird zwischengespeichert.';
});

Zuletzt geändert

Sie können die Methode lastModified verwenden und einen UNIX-Zeitstempel angeben, um das Datum und die Uhrzeit der letzten Modifikation einer Seite festzulegen. Der Client wird seinen Zwischenspeicher weiterhin nutzen, bis sich der Wert der letzten Modifikation ändert.

Flight::route('/nachrichten', function () {
  Flight::lastModified(1234567890);
  echo 'Dieser Inhalt wird zwischengespeichert.';
});

ETag

Das ETag-Caching ähnelt Last-Modified, außer dass Sie eine beliebige Kennung für die Ressource angeben können, die Sie möchten:

Flight::route('/nachrichten', function () {
  Flight::etag('meine-eindeutige-id');
  echo 'Dieser Inhalt wird zwischengespeichert.';
});

Beachten Sie, dass das Aufrufen von lastModified oder etag sowohl den Cache-Wert festlegt als auch überprüft. Wenn der Cache-Wert zwischen den Anfragen gleich ist, sendet Flight sofort eine HTTP 304-Antwort und bricht die Verarbeitung ab.

Learn/frameworkinstance

Framework-Instanz

Anstatt Flight als globale statische Klasse auszuführen, können Sie es optional als ein Objektinstanz ausführen.

require 'flight/autoload.php';

$app = Flight::app();

$app->route('/', function () {
  echo 'Hallo Welt!';
});

$app->start();

Also würden Sie anstelle des Aufrufs der statischen Methode die Instanzmethode mit demselben Namen am Engine-Objekt aufrufen.

Learn/redirects

Weiterleitungen

Sie können die aktuelle Anfrage umleiten, indem Sie die redirect Methode verwenden und eine neue URL übergeben:

Flight::redirect('/neuer/standort');

Standardmäßig sendet Flight einen HTTP-Statuscode 303. Sie können optional einen benutzerdefinierten Code setzen:

Flight::redirect('/neuer/standort', 401);

Learn/views

Ansichten

Flight bietet standardmäßig einige grundlegende Template-Funktionalitäten. Um ein Ansichts-Template anzuzeigen, rufen Sie die Methode render mit dem Namen der Template-Datei und optionalen Template-Daten auf:

Flight::render('hello.php', ['name' => 'Bob']);

Die übergebenen Template-Daten werden automatisch in das Template eingefügt und können wie eine lokale Variable referenziert werden. Template-Dateien sind einfach PHP-Dateien. Wenn der Inhalt der hello.php Template-Datei lautet:

Hallo, <?= $name ?>!

Die Ausgabe wäre:

Hallo, Bob!

Sie können auch manuell Ansichtsvariablen festlegen, indem Sie die Methode set verwenden:

Flight::view()->set('name', 'Bob');

Die Variable name ist nun in allen Ihren Ansichten verfügbar. Sie können also einfach Folgendes tun:

Flight::render('hello');

Beachten Sie, dass beim Festlegen des Namens des Templates in der Render-Methode die Dateierweiterung .php ausgelassen werden kann.

Standardmäßig sucht Flight nach einem views-Verzeichnis für Template-Dateien. Sie können einen alternativen Pfad für Ihre Templates festlegen, indem Sie die folgende Konfiguration setzen:

Flight::set('flight.views.path', '/pfad/zu/ansichten');

Layouts

Es ist üblich, dass Websites eine einzelne Layout-Template-Datei mit sich änderndem Inhalt haben. Um Inhalte zu rendern, die in einem Layout verwendet werden sollen, können Sie einen optionalen Parameter an die render-Methode übergeben.

Flight::render('header', ['heading' => 'Hallo'], 'headerContent');
Flight::render('body', ['body' => 'Welt'], 'bodyContent');

Ihre Ansicht wird dann gespeicherte Variablen namens headerContent und bodyContent haben. Sie können dann Ihr Layout rendern, indem Sie Folgendes tun:

Flight::render('layout', ['title' => 'Startseite']);

Wenn die Template-Dateien wie folgt aussehen:

header.php:

<h1><?= $heading ?></h1>

body.php:

<div><?= $body ?></div>

layout.php:

<html>
  <head>
    <title><?= $title ?></title>
  </head>
  <body>
    <?= $headerContent ?>
    <?= $bodyContent ?>
  </body>
</html>

Die Ausgabe wäre:

<html>
  <head>
    <title>Startseite</title>
  </head>
  <body>
    <h1>Hallo</h1>
    <div>Welt</div>
  </body>
</html>

Individuelle Ansichten

Flight ermöglicht es Ihnen, den Standard-View-Engine einfach durch Registrieren Ihrer eigenen View-Klasse auszutauschen. So verwenden Sie z. B. den Smarty Template-Engine für Ihre Ansichten:

// Smarty-Bibliothek laden
require './Smarty/libs/Smarty.class.php';

// Registrieren Sie Smarty als View-Klasse
// Geben Sie auch eine Rückruffunktion zum Konfigurieren von Smarty beim Laden an
Flight::register('view', Smarty::class, [], function (Smarty $smarty) {
  $smarty->setTemplateDir('./templates/');
  $smarty->setCompileDir('./templates_c/');
  $smarty->setConfigDir('./config/');
  $smarty->setCacheDir('./cache/');
});

// Template-Daten zuweisen
Flight::view()->assign('name', 'Bob');

// Template anzeigen
Flight::view()->display('hello.tpl');

Zu Ihrer Information sollten Sie auch die Standard-Rendermethode von Flight überschreiben:

Flight::map('render', function(string $template, array $data): void {
  Flight::view()->assign($data);
  Flight::view()->display($template);
});

Learn/templates

Ansichten

Flight bietet standardmäßig einige grundlegende Template-Funktionalitäten.

Wenn Sie komplexere Template-Anforderungen haben, finden Sie Beispiele für Smarty und Latte im Abschnitt Benutzerdefinierte Ansichten.

Um eine Ansichtsvorlage anzuzeigen, rufen Sie die render Methode mit dem Namen der Vorlagendatei und optionalen Vorlagedaten auf:

Flight::render('hello.php', ['name' => 'Bob']);

Die von Ihnen übergebenen Vorlagendaten werden automatisch in die Vorlage eingefügt und können wie eine lokale Variable referenziert werden. Vorlagendateien sind einfach PHP-Dateien. Wenn der Inhalt der hello.php Vorlagendatei folgendermaßen aussieht:

Hallo, <?= $name ?>!

Das Ergebnis wäre:

Hallo, Bob!

Sie können auch manuell Ansichtsvariablen festlegen, indem Sie die set Methode verwenden:

Flight::view()->set('name', 'Bob');

Die Variable name steht nun in allen Ihren Ansichten zur Verfügung. Sie können also einfach Folgendes tun:

Flight::render('hello');

Beachten Sie, dass Sie bei der Angabe des Namens der Vorlage in der render Methode die Dateierweiterung .php weglassen können.

Standardmäßig sucht Flight nach einem views-Verzeichnis für Vorlagendateien. Sie können einen alternativen Pfad für Ihre Vorlagen festlegen, indem Sie die folgende Konfiguration setzen:

Flight::set('flight.views.path', '/pfad/zur/vorlagen');

Layouts

Es ist üblich, dass Websites eine einzelne Layout-Vorlagendatei mit wechselndem Inhalt haben. Um Inhalte zu rendern, die in einem Layout verwendet werden sollen, können Sie einen optionalen Parameter an die render Methode übergeben.

Flight::render('header', ['heading' => 'Hallo'], 'headerContent');
Flight::render('body', ['body' => 'Welt'], 'bodyContent');

Ihre Ansicht wird dann gespeicherte Variablen namens headerContent und bodyContent haben. Sie können dann Ihr Layout rendern, indem Sie Folgendes tun:

Flight::render('layout', ['title' => 'Startseite']);

Wenn die Vorlagendateien wie folgt aussehen:

header.php:

<h1><?= $heading ?></h1>

body.php:

<div><?= $body ?></div>

layout.php:

<html>
  <head>
    <title><?= $title ?></title>
  </head>
  <body>
    <?= $headerContent ?>
    <?= $bodyContent ?>
  </body>
</html>

Das Ergebnis wäre:

<html>
  <head>
    <title>Startseite</title>
  </head>
  <body>
    <h1>Hallo</h1>
    <div>Welt</div>
  </body>
</html>

Benutzerdefinierte Ansichten

Flight ermöglicht es Ihnen, den Standard-View-Engine einfach zu ersetzen, indem Sie Ihre eigene View-Klasse registrieren.

Smarty

So verwenden Sie den Smarty Template-Motor für Ihre Ansichten:

// Smarty-Bibliothek laden
require './Smarty/libs/Smarty.class.php';

// Smarty als View-Klasse registrieren
// Geben Sie auch eine Rückruffunktion zur Konfiguration von Smarty beim Laden an
Flight::register('view', Smarty::class, [], function (Smarty $smarty) {
  $smarty->setTemplateDir('./templates/');
  $smarty->setCompileDir('./templates_c/');
  $smarty->setConfigDir('./config/');
  $smarty->setCacheDir('./cache/');
});

// Vorlagendaten zuweisen
Flight::view()->assign('name', 'Bob');

// Vorlage anzeigen
Flight::view()->display('hello.tpl');

Für Vollständigkeit sollten Sie auch die Standard-render Methode von Flight überschreiben:

Flight::map('render', function(string $template, array $data): void {
  Flight::view()->assign($data);
  Flight::view()->display($template);
});

Latte

So verwenden Sie den Latte Template-Motor für Ihre Ansichten:


// Latte als View-Klasse registrieren
// Geben Sie auch eine Rückruffunktion zur Konfiguration von Latte beim Laden an
Flight::register('view', Latte\Engine::class, [], function (Latte\Engine $latte) {
  // Hier werden die Latte Ihre Vorlagen zwischenspeichern, um die Geschwindigkeit zu erhöhen
    // Eine nette Eigenschaft von Latte ist, dass es automatisch Ihren Zwischenspeicher aktualisiert
    // wenn Sie Änderungen an Ihren Vorlagen vornehmen!
    $latte->setTempDirectory(__DIR__ . '/../cache/');

    // Sagen Sie Latte, wo das Stammverzeichnis für Ihre Ansichten sein wird.
    $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../views/'));
});

// Und verpacken Sie es, damit Sie Flight::render() korrekt verwenden können
Flight::map('render', function(string $template, array $data): void {
  // Dies entspricht $latte_engine->render($template, $data);
  echo Flight::view()->render($template, $data);
});

Learn/extending

Erweiterung

Flight ist darauf ausgelegt, ein erweiterbares Framework zu sein. Das Framework wird mit einem Satz von Standardmethoden und -komponenten geliefert, aber es ermöglicht Ihnen, Ihre eigenen Methoden zu mappen, Ihre eigenen Klassen zu registrieren oder sogar bestehende Klassen und Methoden zu überschreiben.

Wenn Sie nach einem DIC (Dependency Injection Container) suchen, gehen Sie zur Dependency Injection Container-Seite.

Mappen von Methoden

Um Ihre eigene einfache benutzerdefinierte Methode zu mappen, verwenden Sie die map Funktion:

// Mappen Sie Ihre Methode
Flight::map('hello', function (string $name) {
  echo "hallo $name!";
});

// Rufen Sie Ihre benutzerdefinierte Methode auf
Flight::hello('Bob');

Dies wird mehr verwendet, wenn Sie Variablen in Ihre Methode übergeben müssen, um einen erwarteten Wert zu erhalten. Die Verwendung der register() Methode wie unten gezeigt ist mehr dazu da, Konfigurationen zu übergeben und dann Ihre vorab konfigurierte Klasse aufzurufen.

Klassen registrieren

Um Ihre eigene Klasse zu registrieren und zu konfigurieren, verwenden Sie die register Funktion:

// Registrieren Sie Ihre Klasse
Flight::register('user', User::class);

// Holen Sie sich eine Instanz Ihrer Klasse
$user = Flight::user();

Die Registrierungsmethode ermöglicht es Ihnen auch, Parameter an den Konstruktor Ihrer Klasse zu übergeben. Wenn Sie Ihre benutzerdefinierte Klasse laden, wird sie somit vorinitialisiert. Sie können die Konstruktorparameter definieren, indem Sie ein zusätzliches Array übergeben. Hier ist ein Beispiel zum Laden einer Datenbankverbindung:

// Klasse mit Konstruktorparametern registrieren
Flight::register('db', PDO::class, ['mysql:host=localhost;dbname=test', 'benutzer', 'passwort']);

// Holen Sie sich eine Instanz Ihrer Klasse
// Dies erstellt ein Objekt mit den definierten Parametern
//
// new PDO('mysql:host=localhost;dbname=test','benutzer','passwort');
//
$db = Flight::db();

// und wenn Sie es später in Ihrem Code benötigen, rufen Sie einfach die gleiche Methode erneut auf
class SomeController {
  public function __construct() {
    $this->db = Flight::db();
  }
}

Wenn Sie einen zusätzlichen Rückrufparameter übergeben, wird dieser sofort nach der Klassenkonstruktion ausgeführt. Dies ermöglicht es Ihnen, jegliche Einrichtungsverfahren für Ihr neues Objekt durchzuführen. Die Rückruffunktion benötigt ein Parameter, eine Instanz des neuen Objekts.

// Der Rückruf wird das konstruierte Objekt erhalten
Flight::register(
  'db',
  PDO::class,
  ['mysql:host=localhost;dbname=test', 'benutzer', 'passwort'],
  function (PDO $db) {
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }
);

Standardmäßig erhalten Sie bei jeder Verwendung Ihrer Klasse eine gemeinsam genutzte Instanz. Um eine neue Instanz einer Klasse zu erhalten, geben Sie einfach false als Parameter ein:

// Gemeinsam genutzte Instanz der Klasse
$shared = Flight::db();

// Neue Instanz der Klasse
$neu = Flight::db(false);

Bitte beachten Sie, dass gemappte Methoden Vorrang vor registrierten Klassen haben. Wenn Sie beide mit demselben Namen deklarieren, wird nur die gemappte Methode aufgerufen.

Überschreiben von Framework-Methoden

Flight ermöglicht es Ihnen, seine Standardfunktionalität anzupassen, um Ihren eigenen Anforderungen gerecht zu werden, ohne dass Sie Code ändern müssen.

Wenn beispielsweise Flight keine URL mit einer Route abgleichen kann, ruft es die notFound-Methode auf, die eine generische HTTP 404-Antwort sendet. Sie können dieses Verhalten überschreiben, indem Sie die map Methode verwenden:

Flight::map('notFound', function() {
  // Benutzerdefinierte 404-Seite anzeigen
  include 'fehler/404.html';
});

Flight ermöglicht es auch, Kernkomponenten des Frameworks zu ersetzen. Zum Beispiel können Sie die Standard-Routenklasse durch Ihre eigene benutzerdefinierte Klasse ersetzen:

// Registrieren Sie Ihre benutzerdefinierte Klasse
Flight::register('router', MyRouter::class);

// Wenn Flight die Router-Instanz lädt, wird Ihre Klasse geladen
$meinrouter = Flight::router();

Framework-Methoden wie map und register können jedoch nicht überschrieben werden. Sie erhalten einen Fehler, wenn Sie es dennoch versuchen.

Learn/json

# JSON

Flight bietet Unterstützung für das Senden von JSON- und JSONP-Antworten. Um eine JSON-Antwort zu senden, übergeben Sie einige Daten, die in JSON kodiert werden sollen:

```php
Flight::json(['id' => 123]);

Für JSONP-Anfragen können Sie optional den Abfrage-Parameter Namen angeben, den Sie verwenden, um Ihre Rückruffunktion zu definieren:

Flight::jsonp(['id' => 123], 'q');

Wenn Sie also eine GET-Anfrage mit ?q=my_func stellen, sollten Sie die Ausgabe erhalten:

my_func({"id":123});

Wenn Sie keinen Abfrageparameter Namen angeben, wird standardmäßig jsonp verwendet.

Learn/autoloading

Autoloading

Autoloading ist ein Konzept in PHP, bei dem Sie ein Verzeichnis oder Verzeichnisse angeben, aus denen Klassen geladen werden sollen. Dies ist wesentlich vorteilhafter als die Verwendung von require oder include, um Klassen zu laden. Es ist auch eine Voraussetzung für die Verwendung von Composer-Paketen.

Standardmäßig wird jede Flight-Klasse dank Composer automatisch für Sie geladen. Wenn Sie jedoch Ihre eigenen Klassen automatisch laden möchten, können Sie die Methode Flight::path verwenden, um ein Verzeichnis anzugeben, aus dem Klassen geladen werden sollen.

Grundlegendes Beispiel

Angenommen, wir haben einen Verzeichnisbaum wie folgt:

# Beispiel-Pfad
/home/user/project/my-flight-project/
├── app
│   ├── cache
│   ├── config
│   ├── controllers - enthält die Controller für dieses Projekt
│   ├── translations
│   ├── UTILS - enthält Klassen nur für diese Anwendung (dies ist absichtlich alles in Großbuchstaben für ein späteres Beispiel)
│   └── views
└── public
    └── css
    └── js
    └── index.php

Sie haben vielleicht festgestellt, dass dies die gleiche Dateistruktur wie diese Dokumentationsseite ist.

Sie können jedes Verzeichnis wie folgt zum Laden angeben:


/**
 * public/index.php
 */

// Fügen Sie einen Pfad zum Autoloader hinzu
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');

/**
 * app/controllers/MyController.php
 */

// Keine Namensräume erforderlich

// Alle automatisch geladenen Klassen sollten Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen)
// Es ist eine Anforderung, dass Sie keinen Unterstrich im Klassennamen haben dürfen
class MyController {

    public function index() {
        // etwas machen
    }
}

Namensräume

Wenn Sie Namensräume haben, ist es tatsächlich sehr einfach, dies zu implementieren. Verwenden Sie die Methode Flight::path(), um das Stammverzeichnis (nicht das Dokumentstammverzeichnis oder den public/-Ordner) Ihrer Anwendung anzugeben.


/**
 * public/index.php
 */

// Fügen Sie einen Pfad zum Autoloader hinzu
Flight::path(__DIR__.'/../');

So könnte Ihr Controller dann aussehen. Schauen Sie sich das folgende Beispiel an, aber achten Sie auf die Kommentare für wichtige Informationen.

/**
 * app/controllers/MyController.php
 */

// Namensräume sind erforderlich
// Namensräume entsprechen der Verzeichnisstruktur
// Namensräume müssen der gleichen Großschreibung wie die Verzeichnisstruktur folgen
// Namensräume und Verzeichnisse dürfen keine Unterstriche enthalten
namespace app\controllers;

// Alle automatisch geladenen Klassen sollten Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen)
// Es ist eine Anforderung, dass Sie keinen Unterstrich im Klassennamen haben dürfen
class MyController {

    public function index() {
        // etwas machen
    }
}

Und wenn Sie eine Klasse in Ihrem UTILS-Verzeichnis automatisch laden möchten, würden Sie im Grunde dasselbe tun:


/**
 * app/UTILS/ArrayHelperUtil.php
 */

// Der Namespace muss der Verzeichnisstruktur und Großschreibung entsprechen (beachten Sie, dass das UTILS-Verzeichnis alles in Großbuchstaben ist
//     wie im obigen Dateibaum)
namespace app\UTILS;

class ArrayHelperUtil {

    public function changeArrayCase(array $array) {
        // etwas machen
    }
}

Install

Installation

Lade die Dateien herunter.

Wenn Sie Composer verwenden, können Sie den folgenden Befehl ausführen:

composer require flightphp/core

ODER Sie können die Dateien herunterladen direkt und sie in Ihr Webverzeichnis extrahieren.

Konfigurieren Sie Ihren Webserver.

Apache

Für Apache bearbeiten Sie Ihre .htaccess-Datei wie folgt:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Hinweis: Wenn Sie Flight in einem Unterverzeichnis verwenden müssen, fügen Sie die Zeile hinzu RewriteBase /subdir/ direkt nach RewriteEngine On hinzu.

Hinweis: Wenn Sie alle Serverdateien schützen möchten, wie z.B. eine db- oder env-Datei. Fügen Sie dies Ihrer .htaccess-Datei hinzu:

RewriteEngine On
RewriteRule ^(.*)$ index.php

Nginx

Für Nginx fügen Sie Folgendes zu Ihrer Serverdeklaration hinzu:

server {
  location / {
    try_files $uri $uri/ /index.php;
  }
}

Erstellen Sie Ihre index.php-Datei.

<?php

// Wenn Sie Composer verwenden, fordern Sie den Autoloader an.
require 'vendor/autoload.php';
// wenn Sie Composer nicht verwenden, laden Sie das Framework direkt
// require 'flight/Flight.php';

// Definieren Sie dann eine Route und weisen Sie eine Funktion zu, um die Anfrage zu bearbeiten.
Flight::route('/', function () {
  echo 'Hallo Welt!';
});

// Starten Sie schließlich das Framework.
Flight::start();

License

Die MIT Lizenz (MIT)

Copyright © 2023 @mikecao, @n0nag0n

Hiermit wird unentgeltlich die Erlaubnis erteilt, von jeder Person, die eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (the "Software") erhält, diese Software ohne Einschränkungen zu nutzen, einschließlich, aber nicht beschränkt auf das Recht, sie zu verwenden, zu kopieren, zu modifizieren, zu fusionieren, zu veröffentlichen, zu verbreiten, unterzulizenzieren und/oder zu verkaufen Kopien der Software sowie Personen, denen die Software überlassen wird, dies unter den folgenden Bedingungen zu tun:

Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk sind in allen Kopien oder wesentlichen Teilen der Software einzubeziehen.

DIE SOFTWARE WIRD "WIE SIE IST" BEREITGESTELLT, OHNE JEGLICHE GEWÄHRLEISTUNG, AUSDRÜCKLICH ODER IMPLIZIERT, EINSCHLIESSLICH DER GEWÄHRLEISTUNG DER MARKTFÄHIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG. UNTER KEINEN UMSTÄNDEN SIND DIE AUTOREN ODER URHEBERRECHTSINHABER HAFTBAR FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNG, OB IN EINER VERTRAGS- ODER DELIKTISCHE HANDLUNG, DIE AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER VERWENDUNG ODER ANDEREN GESCHÄFTEN IN DER SOFTWARE ENTSTEHEN.

About

Was ist Flight?

Flight ist ein schnelles, einfaches, erweiterbares Framework für PHP. Es ist ziemlich vielseitig und kann für den Aufbau beliebiger Arten von Webanwendungen verwendet werden. Es ist mit Einfachheit im Sinn aufgebaut und so geschrieben, dass es leicht zu verstehen und zu verwenden ist.

Flight ist ein großartiges Einsteiger-Framework für diejenigen, die neu in PHP sind und lernen möchten, wie man Webanwendungen erstellt. Es ist auch ein großartiges Framework für erfahrene Entwickler, die mehr Kontrolle über ihre Webanwendungen haben möchten. Es ist darauf ausgelegt, leicht eine RESTful API, eine einfache Webanwendung oder eine komplexe Webanwendung zu erstellen.

Schnellstart

<?php

// Wenn mit Composer installiert
require 'vendor/autoload.php';
// oder wenn manuell per Zip-Datei installiert
// require 'flight/Flight.php';

Flight::route('/', function() {
  echo 'Hallo Welt!';
});

Flight::route('/json', function() {
  Flight::json(['hallo' => 'Welt']);
});

Flight::start();

Einfach genug, oder? Erfahren Sie mehr über Flight in der Dokumentation!

Skelett/Vorlagen-App

Es gibt eine Beispiel-App, die Ihnen den Einstieg in das Flight Framework erleichtern kann. Gehen Sie zu flightphp/skeleton für Anweisungen zum Einstieg! Sie können auch die Beispiele Seite besuchen, um sich inspirieren zu lassen, was Sie mit Flight tun können.

Community

Wir sind auf Matrix! Chatten Sie mit uns unter #flight-php-framework:matrix.org.

Mitwirken

Es gibt zwei Möglichkeiten, wie Sie zu Flight beitragen können:

  1. Sie können zum Kernframework beitragen, indem Sie das Kern-Repository besuchen.
  2. Sie können zur Dokumentation beitragen. Diese Dokumentationswebsite wird auf Github gehostet. Wenn Sie einen Fehler bemerken oder etwas besser ausarbeiten möchten, können Sie es gerne korrigieren und einen Pull-Request einreichen! Wir bemühen uns, auf dem Laufenden zu bleiben, aber Aktualisierungen und Sprachübersetzungen sind willkommen.

Anforderungen

Flight erfordert PHP 7.4 oder höher.

Hinweis: PHP 7.4 wird unterstützt, weil zum Zeitpunkt des Schreibens (2024) PHP 7.4 die Standardversion für einige LTS-Linux-Distributionen ist. Ein erzwungener Wechsel zu PHP >8 würde für diese Benutzer viele Kopfschmerzen verursachen. Das Framework unterstützt auch PHP >8.

Lizenz

Flight wird unter der MIT Lizenz veröffentlicht.

Awesome-plugins/php_cookie

Cookies

overclokk/cookie ist eine einfache Bibliothek zum Verwalten von Cookies in Ihrer App.

Installation

Die Installation ist mit Composer einfach.

composer require overclokk/cookie

Verwendung

Die Verwendung ist so einfach wie das Registrieren einer neuen Methode in der Flight-Klasse.


use Overclokk\Cookie\Cookie;

/*
 * Setzen Sie dies in Ihrer Bootstrap- oder public/index.php-Datei
 */

Flight::register('cookie', Cookie::class);

/**
 * ExampleController.php
 */

class ExampleController {
    public function login() {
        // Setze ein Cookie

        // Sie möchten, dass dies falsch ist, damit Sie eine neue Instanz erhalten
        // verwenden Sie den folgenden Kommentar, wenn Sie eine Autovervollständigung wünschen
        /** @var \Overclokk\Cookie\Cookie $cookie */
        $cookie = Flight::cookie(false);
        $cookie->set(
            'stay_logged_in', // Name des Cookies
            '1', // der Wert, den Sie setzen möchten
            86400, // Anzahl der Sekunden, die das Cookie dauern soll
            '/', // Pfad, auf dem das Cookie verfügbar sein wird
            'example.com', // Domain, auf der das Cookie verfügbar sein wird
            true, // das Cookie wird nur über eine sichere HTTPS-Verbindung übertragen
            true // das Cookie ist nur über das HTTP-Protokoll verfügbar
        );

        // optional, wenn Sie die Standardwerte beibehalten und eine schnelle Möglichkeit haben möchten, ein Cookie lange zu setzen
        $cookie->forever('stay_logged_in', '1');
    }

    public function home() {
        // Überprüfen Sie, ob Sie das Cookie haben
        if (Flight::cookie()->has('stay_logged_in')) {
            // bringe sie z.B. in den Dashboard-Bereich.
            Flight::redirect('/dashboard');
        }
    }
}

Awesome-plugins/php_encryption

PHP-Verschlüsselung

defuse/php-encryption ist eine Bibliothek, die zum Verschlüsseln und Entschlüsseln von Daten verwendet werden kann. Das Einrichten und Starten ist ziemlich einfach, um mit der Verschlüsselung und Entschlüsselung von Daten zu beginnen. Sie haben ein großartiges Tutorial, das dabei hilft, die Grundlagen zur Verwendung der Bibliothek sowie wichtige Sicherheitsaspekte in Bezug auf Verschlüsselung zu erklären.

Installation

Die Installation ist einfach mit Composer.

composer require defuse/php-encryption

Einrichtung

Dann müssen Sie einen Verschlüsselungsschlüssel generieren.

vendor/bin/generate-defuse-key

Das wird einen Schlüssel ausgeben, den Sie sicher aufbewahren müssen. Sie könnten den Schlüssel in Ihrer app/config/config.php-Datei im Array am Ende der Datei aufbewahren. Auch wenn es nicht der perfekte Ort ist, ist es zumindest etwas.

Verwendung

Nun, da Sie die Bibliothek und einen Verschlüsselungsschlüssel haben, können Sie damit beginnen, Daten zu verschlüsseln und zu entschlüsseln.


use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;

/*
 * In Ihrer Bootstrap- oder public/index.php-Datei festlegen
 */

// Verschlüsselungsmethode
Flight::map('encrypt', function($rohdaten) {
    $verschlüsselungsschlüssel = /* $config['encryption_key'] oder ein file_get_contents davon, wo Sie den Schlüssel platziert haben */;
    return Crypto::encrypt($rohdaten, Key::loadFromAsciiSafeString($verschlüsselungsschlüssel));
});

// Entschlüsselungsmethode
Flight::map('decrypt', function($verschlüsselte_daten) {
    $verschlüsselungsschlüssel = /* $config['encryption_key'] oder ein file_get_contents davon, wo Sie den Schlüssel platziert haben */;
    try {
        $rohdaten = Crypto::decrypt($verschlüsselte_daten, Key::loadFromAsciiSafeString($verschlüsselungsschlüssel));
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
        // Ein Angriff! Entweder der falsche Schlüssel wurde geladen oder der Geheimtext hat sich seit seiner Erstellung geändert -- entweder in der Datenbank korrupt oder absichtlich von Eve modifiziert, um einen Angriff durchzuführen.

        // ... diesen Fall auf eine Art und Weise behandeln, die für Ihre Anwendung geeignet ist ...
    }
    return $rohdaten;
});

Flight::route('/encrypt', function() {
    $verschlüsselte_daten = Flight::encrypt('Das ist ein Geheimnis');
    echo $verschlüsselte_daten;
});

Flight::route('/decrypt', function() {
    $verschlüsselte_daten = '...'; // Verschlüsselte Daten von irgendwoher erhalten
    $entschlüsselte_daten = Flight::decrypt($verschlüsselte_daten);
    echo $entschlüsselte_daten;
});

Awesome-plugins/php_file_cache

Wruczek/PHP-File-Cache

Leichte, einfache und eigenständige PHP-In-File-Caching-Klasse

Vorteile

Installation

Installiere über Composer:

composer require wruczek/php-file-cache

Verwendung

Die Verwendung ist ziemlich einfach.

use Wruczek\PhpFileCache\PhpFileCache;

$app = Flight::app();

// Sie geben das Verzeichnis, in dem der Cache gespeichert wird, dem Konstruktor an
$app->register('cache', PhpFileCache::class, [ __DIR__ . '/../cache/' ], function(PhpFileCache $cache) {

    // Dies stellt sicher, dass der Cache nur im Produktionsmodus verwendet wird
    // UMGEBUNG ist eine Konstante, die in Ihrer Startdatei oder an anderer Stelle in Ihrer App festgelegt ist
    $cache->setDevMode(ENVIRONMENT === 'development');
});

Dann können Sie es in Ihrem Code wie folgt verwenden:


// Cache-Instanz abrufen
$cache = Flight::cache();
$data = $cache->refreshIfExpired('simple-cache-test', function () {
    return date("H:i:s"); // Daten zurückgeben, die zwischengespeichert werden sollen
}, 10); // 10 Sekunden

// oder
$data = $cache->retrieve('simple-cache-test');
if(empty($data)) {
    $data = date("H:i:s");
    $cache->store('simple-cache-test', $data, 10); // 10 Sekunden
}

Dokumentation

Besuchen Sie https://github.com/Wruczek/PHP-File-Cache für die vollständige Dokumentation und stellen Sie sicher, dass Sie den Beispiele Ordner ansehen.

Awesome-plugins/index

Tolle Plugins

Flight ist unglaublich erweiterbar. Es gibt eine Reihe von Plugins, die dazu verwendet werden können, Funktionalitäten Ihrer Flight-Anwendung hinzuzufügen. Einige werden offiziell vom Flight-Team unterstützt, während andere Mikro-/Lite-Bibliotheken sind, um Ihnen den Einstieg zu erleichtern.

Caching

Caching ist ein großartiger Weg, um Ihre Anwendung zu beschleunigen. Es gibt einige Caching-Bibliotheken, die mit Flight verwendet werden können.

Debugging

Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt einige Plugins, die Ihr Debugging-Erlebnis verbessern können.

Datenbanken

Datenbanken sind das Herzstück vieler Anwendungen. So speichern und abrufen Sie Daten. Einige Datenbank-Bibliotheken sind einfach Wrapper zum Schreiben von Abfragen, während andere vollwertige ORMs sind.

Sitzung

Sitzungen sind nicht wirklich nützlich für APIs, aber beim Erstellen einer Webanwendung können Sitzungen wichtig sein, um Zustands- und Anmeldeinformationen zu speichern.

Templating

Templates sind für jede Webanwendung mit einer Benutzeroberfläche unerlässlich. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können.

Mitwirken

Haben Sie ein Plugin, das Sie teilen möchten? Senden Sie einen Pull-Request, um es der Liste hinzuzufügen!

Awesome-plugins/pdo_wrapper

PdoWrapper PDO Hilfsklasse

Flight wird mit einer Hilfsklasse für PDO geliefert. Es ermöglicht Ihnen, Ihre Datenbank einfach abzufragen mit all der vorbereiteten/ausführen/fetchAll() Verrücktheit. Es vereinfacht erheblich, wie Sie auf Ihre Datenbank zugreifen können. Jedes Zeilenergebnis wird als eine Flug Sammlungsklasse zurückgegeben, die es Ihnen ermöglicht, auf Ihre Daten über die Array-Syntax oder Objektsyntax zuzugreifen.

Registrierung der PDO Hilfsklasse

// Registrieren Sie die PDO Hilfsklasse
Flight::register('db', \flight\database\PdoWrapper::class, ['mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\'',
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_STRINGIFY_FETCHES => false,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]
]);

Verwendung

Dieses Objekt erweitert PDO, daher sind alle normalen PDO-Methoden verfügbar. Die folgenden Methoden wurden hinzugefügt, um Abfragen an die Datenbank einfacher zu machen:

runQuery(string $sql, array $params = []): PDOStatement

Verwenden Sie dies für INSERTS, UPDATES oder wenn Sie planen, ein SELECT in einer Schleife zu verwenden

$db = Flight::db();
$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]);
while($row = $statement->fetch()) {
    // ...
}

// Oder Schreiben in die Datenbank
$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]);
$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]);

fetchField(string $sql, array $params = []): mixed

Holt das erste Feld aus der Abfrage

$db = Flight::db();
$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]);

fetchRow(string $sql, array $params = []): array

Holt eine Zeile aus der Abfrage

$db = Flight::db();
$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]);
echo $row['name'];
// oder
echo $row->name;

fetchAll(string $sql, array $params = []): array

Holt alle Zeilen aus der Abfrage

$db = Flight::db();
$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]);
foreach($rows as $row) {
    echo $row['name'];
    // oder
    echo $row->name;
}

Hinweis zur Verwendung von IN() Syntax

Hier gibt es auch einen hilfreichen Wrapper für IN() Anweisungen. Sie können einfach ein einzelnes Fragezeichen als Platzhalter für IN() übergeben und dann ein Array von Werten. Hier ist ein Beispiel, wie das aussehen könnte:

$db = Flight::db();
$name = 'Bob';
$company_ids = [1,2,3,4,5];
$rows = $db->fetchAll("SELECT id, name FROM table WHERE name = ? AND company_id IN (?)", [ $name, $company_ids ]);

Vollständiges Beispiel

// Beispielroute und wie Sie diesen Wrapper verwenden würden
Flight::route('/users', function () {
    // Alle Benutzer abrufen
    $users = Flight::db()->fetchAll('SELECT * FROM users');

    // Alle Benutzer streamen
    $statement = Flight::db()->runQuery('SELECT * FROM users');
    while ($user = $statement->fetch()) {
        echo $user['name'];
        // oder echo $user->name;
    }

    // Einen einzelnen Benutzer abrufen
    $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]);

    // Einen einzelnen Wert abrufen
    $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users');

    // Besondere IN() Syntax, um zu helfen (stellen Sie sicher, dass IN großgeschrieben ist)
    $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]);
    // Sie könnten auch dies tun
    $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']);

    // Einen neuen Benutzer einfügen
    Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']);
    $insert_id = Flight::db()->lastInsertId();

    // Einen Benutzer aktualisieren
    Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]);

    // Einen Benutzer löschen
    Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]);

    // Die Anzahl der betroffenen Zeilen abrufen
    $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']);
    $affected_rows = $statement->rowCount();

});

Awesome-plugins/session

Ghostff/Sitzung

PHP-Sitzungsmanager (nicht blockierend, Flash, Segment, Sitzungsverschlüsselung). Verwendet PHP open_ssl für die optionale Verschlüsselung/Entschlüsselung von Sitzungsdaten. Unterstützt Datei, MySQL, Redis und Memcached.

Installation

Mit Composer installieren.

composer require ghostff/session

Grundkonfiguration

Sie müssen nichts übergeben, um die Standardeinstellungen für Ihre Sitzung zu verwenden. Weitere Einstellungen finden Sie im Github Readme.


use Ghostff\Session\Session;

require 'vendor/autoload.php';

$app = Flight::app();

$app->register('session', Session::class);

// Eine Sache, die Sie beachten müssen, ist, dass Sie bei jedem Seitenaufruf Ihre Sitzung bestätigen müssen
// oder Sie müssen auto_commit in Ihrer Konfiguration ausführen.

Einfaches Beispiel

Hier ist ein einfaches Beispiel, wie Sie dies verwenden könnten.

Flight::route('POST /login', function() {
    $session = Flight::session();

    // Führen Sie hier Ihre Anmelde-Logik aus
    // Passwort validieren, usw.

    // Wenn die Anmeldung erfolgreich ist
    $session->set('is_logged_in', true);
    $session->set('user', $user);

    // Jedes Mal, wenn Sie in die Sitzung schreiben, müssen Sie es bewusst bestätigen.
    $session->commit();
});

// Diese Überprüfung könnte in der Logik der eingeschränkten Seite oder in Middleware eingebettet sein.
Flight::route('/some-restricted-page', function() {
    $session = Flight::session();

    if(!$session->get('is_logged_in')) {
        Flight::redirect('/login');
    }

    // Führen Sie hier Ihre Logik für die eingeschränkte Seite aus
});

// Die Middleware-Version
Flight::route('/some-restricted-page', function() {
    // Reguläre Seitelogik
})->addMiddleware(function() {
    $session = Flight::session();

    if(!$session->get('is_logged_in')) {
        Flight::redirect('/login');
    }
});

Komplexeres Beispiel

Hier ist ein komplexeres Beispiel, wie Sie dies verwenden könnten.


use Ghostff\Session\Session;

require 'vendor/autoload.php';

$app = Flight::app();

// Legen Sie einen benutzerdefinierten Pfad für Ihre Sitzungskonfigurationsdatei fest und geben Sie eine zufällige Zeichenfolge für die Sitzungs-ID an
$app->register('session', Session::class, [ 'Pfad/zur/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) {
    // oder Sie können Konfigurationsoptionen manuell überschreiben
        $session->updateConfiguration([
            // Wenn Sie Ihre Sitzungsdaten in einer Datenbank speichern möchten (gut, wenn Sie etwas Ähnliches wie "Melden Sie mich von allen Geräten ab" möchten)
            Session::CONFIG_DRIVER        => Ghostff\Session\Drivers\MySql::class,
            Session::CONFIG_ENCRYPT_DATA  => true,
            Session::CONFIG_SALT_KEY      => hash('sha256', 'mein-super-GEH3IM3S-Salz'), // bitte ändern Sie dies in etwas anderes
            Session::CONFIG_AUTO_COMMIT   => true, // tun Sie dies nur, wenn es erforderlich ist und/oder es schwierig ist, Ihre Sitzung zu bestätigen.
                                                // zusätzlich könnten Sie Flight::after('start', function() { Flight::session()->commit(); }); ausführen
            Session::CONFIG_MYSQL_DS         => [
                'driver'    => 'mysql',             # Datenbanktreiber für PDO-DSN z.B. (mysql:host=...;dbname=...)
                'host'      => '127.0.0.1',         # Datenbank-Host
                'db_name'   => 'meine_app_datenbank',   # Datenbankname
                'db_table'  => 'sitzungen',          # Datenbanktabelle
                'db_user'   => 'root',              # Datenbankbenutzername
                'db_pass'   => '',                  # Datenbankpasswort
                'persistent_conn'=> false,          # Vermeiden Sie den Overhead beim Herstellen einer neuen Verbindung jedes Mal, wenn ein Skript mit einer Datenbank sprechen muss, was zu einer schnelleren Webanwendung führt. FINDEN SIE IHREN EIGENEN WEG
            ]
        ]);
    }
);

Dokumentation

Besuchen Sie das Github Readme für die vollständige Dokumentation. Die Konfigurationsoptionen sind im default_config.php gut dokumentiert. Der Code ist einfach zu verstehen, wenn Sie dieses Paket selbst durchgehen möchten.

Awesome-plugins/tracy_extensions

Tracy Flight Panel Erweiterungen

Dies ist ein Satz von Erweiterungen, um die Arbeit mit Flight etwas umfangreicher zu gestalten.

Dies ist das Panel

Flight Bar

Und jedes Panel zeigt sehr hilfreiche Informationen über Ihre Anwendung an!

Flight Daten Flight Datenbank Flight Anfrage

Installation

Führen Sie composer require flightphp/tracy-extensions --dev aus und los geht's!

Konfiguration

Es gibt sehr wenig Konfiguration, die Sie durchführen müssen, um damit zu beginnen. Sie müssen den Tracy-Debugger initiieren, bevor Sie dies verwenden https://tracy.nette.org/en/guide:

<?php

use Tracy\Debugger;
use flight\debug\tracy\TracyExtensionLoader;

// Bootstrap-Code
require __DIR__ . '/vendor/autoload.php';

Debugger::enable();
// Sie müssen möglicherweise Ihre Umgebung mit Debugger::enable(Debugger::DEVELOPMENT) angeben

// Wenn Sie Datenbankverbindungen in Ihrer App verwenden, gibt es einen
// erforderlichen PDO-Wrapper, der NUR IN DER ENTWICKLUNG verwendet werden soll (bitte nicht in der Produktion!)
// Es hat dieselben Parameter wie eine reguläre PDO-Verbindung
$pdo = new PdoQueryCapture('sqlite:test.db', 'benutzer', 'passwort');
// oder wenn Sie dies an das Flight-Framework anhängen
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'benutzer', 'passwort']);
// Jetzt, wenn Sie eine Abfrage erstellen, werden Zeit, Abfrage und Parameter erfasst

// Hier werden die Punkte verbunden
if(Debugger::$showBar === true) {
    // Dies muss falsch sein, damit Tracy tatsächlich gerendert werden kann :(
    Flight::set('flight.content_length', false);
    new TracyExtensionLoader(Flight::app());
}

// Weiterer Code

Flight::start();

Zusätzliche Konfiguration

Sitzungsdaten

Wenn Sie einen benutzerdefinierten Sitzungs-Handler haben (wie z.B. ghostff/session), können Sie beliebige Sitzungsdatenarrays an Tracy übergeben, und es wird automatisch ausgegeben. Sie geben es mit dem session_data-Schlüssel im zweiten Parameter des Konstruktors von TracyExtensionLoader an.


use Ghostff\Session\Session;

require 'vendor/autoload.php';

$app = Flight::app();

$app->register('session', Session::class);

if(Debugger::$showBar === true) {
    // Dies muss falsch sein, damit Tracy tatsächlich gerendert werden kann :(
    Flight::set('flight.content_length', false);
    new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}

// Routen und andere Dinge...

Flight::start();

Latte

Wenn Latte in Ihrem Projekt installiert ist, können Sie das Latte-Panel verwenden, um Ihre Templates zu analysieren. Sie können die Latte-Instanz dem Konstruktor von TracyExtensionLoader mit dem Schlüssel latte im zweiten Parameter übergeben.



use Latte\Engine;

require 'vendor/autoload.php';

$app = Flight::app();

$app->register('latte', Engine::class, [], function($latte) {
    $latte->setTempDirectory(__DIR__ . '/temp');

    // Hier fügen Sie das Latte-Panel zu Tracy hinzu
    $latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});

if(Debugger::$showBar === true) {
    // Dies muss falsch sein, damit Tracy tatsächlich gerendert werden kann :(
    Flight::set('flight.content_length', false);
    new TracyExtensionLoader(Flight::app());
}

Awesome-plugins/tracy

Tracy

Tracy ist ein erstaunlicher Fehlerhandler, der mit Flight verwendet werden kann. Es verfügt über eine Reihe von Panels, die Ihnen bei der Fehlerbehebung Ihrer Anwendung helfen können. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. Das Flight-Team hat speziell für Flight-Projekte mit dem flightphp/tracy-extensions Plugin einige Panels erstellt.

Installation

Installiere es mit Composer. Und in der Tat möchten Sie dies ohne die Entwicklerversion installieren, da Tracy mit einem Produktionsfehlerbehandlungskomponente geliefert wird.

composer require tracy/tracy

Grundkonfiguration

Es gibt einige grundlegende Konfigurationsoptionen, um loszulegen. Weitere Informationen dazu finden Sie in der Tracy-Dokumentation.


require 'vendor/autoload.php';

use Tracy\Debugger;

// Aktiviere Tracy
Debugger::enable();
// Debugger::enable(Debugger::DEVELOPMENT) // Manchmal müssen Sie explizit sein (auch Debugger::PRODUCTION)
// Debugger::enable('23.75.345.200'); // Sie können auch ein Array von IP-Adressen bereitstellen

// Hier werden Fehler und Ausnahmen protokolliert. Stellen Sie sicher, dass dieses Verzeichnis vorhanden ist und beschreibbar ist.
Debugger::$logDirectory = __DIR__ . '/../log/';
Debugger::$strictMode = true; // alle Fehler anzeigen
// Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // alle Fehler außer veralteten Hinweisen
if (Debugger::$showBar) {
    $app->set('flight.content_length', false); // Wenn die Debugger-Leiste sichtbar ist, kann die Inhaltslänge nicht von Flight festgelegt werden

    // Dies ist spezifisch für die Tracy-Erweiterung für Flight, wenn Sie diese eingeschlossen haben
    // Andernfalls kommentieren Sie dies aus.
    new TracyExtensionLoader($app);
}

Hilfreiche Tipps

Wenn Sie Ihren Code debuggen, gibt es einige sehr hilfreiche Funktionen, um Daten für Sie auszugeben.

Awesome-plugins/active_record

Flight Active Record

Eine aktive Aufzeichnung mappt eine Datenbank-Entität auf ein PHP-Objekt. Einfach ausgedrückt, wenn Sie eine Benutzertabelle in Ihrer Datenbank haben, können Sie eine Zeile in dieser Tabelle in eine Benutzer-Klasse und ein $benutzer-Objekt in Ihrer Codebasis "übersetzen". Siehe Beispiel.

Basisbeispiel

Nehmen wir an, Sie haben die folgende Tabelle:

CREATE TABLE benutzer (
    id INTEGER PRIMARY KEY, 
    name TEXT, 
    passwort TEXT 
);

Jetzt können Sie eine neue Klasse einrichten, um diese Tabelle darzustellen:

/**
 * Eine ActiveRecord-Klasse ist normalerweise im Singular
 * 
 * Es wird dringend empfohlen, die Eigenschaften der Tabelle hier als Kommentare hinzuzufügen
 * 
 * @property int    $id
 * @property string $name
 * @property string $password
 */ 
class Benutzer extends flight\ActiveRecord {
    public function __construct($datenbankverbindung)
    {
        // Sie können es auf diese Weise festlegen
        parent::__construct($datenbankverbindung, 'benutzer');
        // oder so
        parent::__construct($datenbankverbindung, null, [ 'tabelle' => 'benutzer']);
    }
}

Jetzt schauen Sie zu, wie das Magie geschieht!

// für sqlite
$datenbankverbindung = new PDO('sqlite:test.db'); // dies dient nur als Beispiel, wahrscheinlich würden Sie eine echte Datenbankverbindung verwenden

// für mysql
$datenbankverbindung = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'benutzername', 'passwort');

// oder mysqli
$datenbankverbindung = new mysqli('localhost', 'benutzername', 'passwort', 'test_db');
// oder mysqli mit nicht objektbasierter Erstellung
$datenbankverbindung = mysqli_connect('localhost', 'benutzername', 'passwort', 'test_db');

$benutzer = new Benutzer($datenbankverbindung);
$benutzer->name = 'Bobby Tables';
$benutzer->password = password_hash('ein cooles passwort');
$benutzer->einfügen();
// oder $benutzer->speichern();

echo $benutzer->id; // 1

$benutzer->name = 'Joseph Mamma';
$benutzer->password = password_hash('nochmal ein cooles passwort!!!');
$benutzer->einfügen();
// hier würde $benutzer->speichern() nicht funktionieren, es würde annehmen, dass es ein Update ist!

echo $benutzer->id; // 2

Und es war so einfach, einen neuen Benutzer hinzuzufügen! Jetzt, da es eine Benutzerzeile in der Datenbank gibt, wie holen Sie sie heraus?

$benutzer->find(1); // finde id = 1 in der Datenbank und gib sie zurück.
echo $benutzer->name; // 'Bobby Tables'

Und wenn Sie alle Benutzer finden möchten?

$benutzer = $benutzer->alleFinden();

Was ist mit einer bestimmten Bedingung?

$benutzer = $benutzer->wie('name', '%mamma%')->alleFinden();

Sehen Sie, wie viel Spaß das macht? Lassen Sie uns es installieren und loslegen!

Installation

Einfach mit Composer installieren

composer require flightphp/active-record 

Verwendung

Dies kann als eigenständige Bibliothek oder mit dem Flight PHP Framework verwendet werden. Ganz wie Sie möchten.

Eigenständig

Stellen Sie sicher, dass Sie einfach eine PDO-Verbindung an den Konstruktor übergeben.

$pdo_verbindung = new PDO('sqlite:test.db'); // dies dient nur als Beispiel, wahrscheinlich würden Sie eine echte Datenbankverbindung verwenden

$Benutzer = new Benutzer($pdo_verbindung);

Flight PHP Framework

Wenn Sie das Flight PHP Framework verwenden, können Sie die ActiveRecord-Klasse als Dienst registrieren (aber das müssen Sie ehrlich gesagt nicht).

Flight::register('benutzer', 'Benutzer', [ $pdo_verbindung ]);

// dann können Sie es in einem Controller, einer Funktion usw. so verwenden

Flight::benutzer()->find(1);

CRUD-Funktionen

find($id = null) : boolean|ActiveRecord

Findet einen Datensatz und weist ihn dem aktuellen Objekt zu. Wenn Sie eine Art $id übergeben, wird es eine Abfrage über den Primärschlüssel mit diesem Wert durchführen. Wenn nichts übergeben wird, wird es einfach den ersten Datensatz in der Tabelle finden.

Zusätzlich können Sie ihm andere Hilfsmethoden übergeben, um Ihre Tabelle abzufragen.

// finde einen Datensatz mit bestimmten Bedingungen im Voraus
$benutzer->nichtNull('passwort')->orderBy('id DESC')->find();

// finde einen Datensatz anhand einer bestimmten ID
$id = 123;
$benutzer->find($id);

alleFinden(): array<int,ActiveRecord>

Findet alle Datensätze in der von Ihnen angegebenen Tabelle.

$benutzer->alleFinden();

isHydrated(): boolean (v0.4.0)

Gibt true zurück, wenn der aktuelle Datensatz hydratisiert wurde (aus der Datenbank abgerufen).

$benutzer->find(1);
// wenn ein Datensatz mit Daten gefunden wird...
$benutzer->isHydrated(); // true

einfügen(): boolean|ActiveRecord

Fügt den aktuellen Datensatz in die Datenbank ein.

$benutzer = new Benutzer($pdo_verbindung);
$benutzer->name = 'demo';
$benutzer->passwort = md5('demo');
$benutzer->einfügen();

aktualisieren(): boolean|ActiveRecord

Aktualisiert den aktuellen Datensatz in der Datenbank.

$benutzer->größerAls('id', 0)->orderBy('id desc')->find();
$benutzer->email = 'test@example.com';
$benutzer->aktualisieren();

speichern(): boolean|ActiveRecord

Fügt den aktuellen Datensatz in die Datenbank ein oder aktualisiert ihn. Wenn der Datensatz eine ID hat, wird er aktualisiert, andernfalls wird er eingefügt.

$benutzer = new Benutzer($pdo_verbindung);
$benutzer->name = 'demo';
$benutzer->passwort = md5('demo');
$benutzer->speichern();

Hinweis: Wenn Sie Beziehungen in der Klasse definiert haben, wird es diese Beziehungen auch rekursiv speichern, wenn sie definiert, instanziiert und schmutzige Daten zum Aktualisieren haben. (v0.4.0 und höher)

löschen(): boolean

Löscht den aktuellen Datensatz aus der Datenbank.

$benutzer->gt('id', 0)->orderBy('id desc')->find();
$benutzer->löschen();

Sie können auch mehrere Datensätze löschen, indem Sie zuerst eine Abfrage ausführen.

$benutzer->wie('name', 'Bob%')->löschen();

schmutzig(array $schmutzig = []): ActiveRecord

Schmutzige Daten beziehen sich auf die Daten, die in einem Datensatz geändert wurden.

$benutzer->größerAls('id', 0)->orderBy('id desc')->find();

// bis zu diesem Zeitpunkt ist nichts "schmutzig".

$benutzer->email = 'test@example.com'; // jetzt wird die E-Mail als "schmutzig" betrachtet, da sie geändert wurde.
$benutzer->aktualisieren();
// jetzt gibt es keine schmutzigen Daten, weil sie aktualisiert und in der Datenbank gespeichert wurden

$benutzer->passwort = password_hash()'neuespasswort'); // jetzt ist dies schmutzig
$benutzer->schmutzig(); // ohne Parameter zu übergeben werden alle schmutzigen Einträge gelöscht.
$benutzer->aktualisieren(); // nichts wird aktualisiert, da nichts als schmutzig erfasst wurde.

$benutzer->schmutzig([ 'name' => 'etwas', 'passwort' => password_hash('ein anderes passwort') ]);
$benutzer->aktualisieren(); // sowohl name als auch passwort werden aktualisiert.

kopierenVon(array $daten): ActiveRecord (v0.4.0)

Dies ist ein Alias für die schmutzig()-Methode. Es ist etwas klarer, was Sie tun.

$benutzer->kopierenVon([ 'name' => 'etwas', 'passwort' => password_hash('ein anderes passwort') ]);
$benutzer->aktualisieren(); // sowohl name als auch passwort werden aktualisiert.

istSchmutzig(): boolean (v0.4.0)

Gibt true zurück, wenn der aktuelle Datensatz geändert wurde.

$benutzer->größerAls('id', 0)->orderBy('id desc')->find();
$benutzer->email = 'test@e-mail.com';
$benutzer->istSchmutzig(); // true

zurücksetzen(bool $querydaten_einschließen = true): ActiveRecord

Setzt den aktuellen Datensatz auf seinen ursprünglichen Zustand zurück. Dies ist wirklich nützlich, um es in Schleifenverhalten zu verwenden. Wenn Sie true übergeben, werden auch die Abfragedaten zurückgesetzt, die verwendet wurden, um das aktuelle Objekt zu finden (Standardverhalten).

$benutzer = $benutzer->größerAls('id', 0)->orderBy('id desc')->find();
$benutzer_firma = new BenutzerFirma($pdo_verbindung);

foreach($benutzer as $benutzer) {
    $benutzer_firma->zurücksetzen(); // mit einem sauberen Blatt beginnen
    $benutzer_firma->benutzer_id = $benutzer->id;
    $benutzer_firma->firmen_id = $einige_firmen_id;
    $benutzer_firma->einfügen();
}

getErstelltesSql(): string (v0.4.1)

Nachdem Sie eine find(), alleFinden(), einfügen(), aktualisieren() oder speichern()-Methode ausgeführt haben, können Sie das erstellte SQL abrufen und für Debugging-Zwecke verwenden.

SQL-Abfragemethoden

auswählen(string $feld1 [, string $feld2 ... ])

Sie können nur einige der Spalten in einer Tabelle auswählen, wenn Sie möchten (es ist effizienter bei sehr breiten Tabellen mit vielen Spalten)

$benutzer->auswählen('id', 'name')->find();

von(string $tabelle)

Sie können technisch gesehen auch eine andere Tabelle wählen! Warum auch nicht?!

$benutzer->auswählen('id', 'name')->von('benutzer')->find();

beitreten(string $tabellenname, string $beitrittsbedingung)

Sie können sogar zu einer anderen Tabelle in der Datenbank verbinden.

$benutzer->beitreten('kontakte', 'kontakte.benutzer_id = benutzer.id')->find();

wo(string $wo_bedingungen)

Sie können benutzerdefinierte where-Argumente festlegen (Sie können keine Parameter in dieser where-Anweisung festlegen)

$benutzer->wo('id=1 AND name="demo"')->find();

Sicherheitshinweis - Sie könnten versucht sein, etwas wie $benutzer->wo("id = '{$id}' AND name = '{$name}'")->find(); zu tun. BITTE NICHT TUN! Dies ist anfällig für sogenannte SQL-Injection-Angriffe. Es gibt viele Artikel online, bitte googeln Sie "sql injection attacks php" und Sie werden viele Artikel zu diesem Thema finden. Der richtige Umgang damit dieser Bibliothek ist anstelle dieser wo()-Methode, würden Sie etwas wie $benutzer->eq('id', $id)->eq('name', $name)->find(); verwenden. Wenn Sie dies unbedingt tun müssen, hat die PDO-Bibliothek $pdo->quote($var) zum Escapen für Sie. Erst nach Verwendung von quote() können Sie es in einer wo()-Anweisung verwenden.

gruppe(string $group_by_statement)/groupBy(string $group_by_statement)

Gruppieren Sie Ihre Ergebnisse nach einer bestimmten Bedingung.

$benutzer->auswählen('COUNT(*) as anzahl')->groupBy('name')->alleFinden();

ordnen(string $order_by_statement)/orderBy(string $order_by_statement)

Sortieren Sie die zurückgegebene Abfrage auf bestimmte Weise.

$benutzer->orderBy('name DESC')->find();

limit(string $limit)/limit(int $offset, int $limit)

Begrenzen Sie die Anzahl der zurückgegebenen Datensätze. Wenn Sie eine zweite Zahl übergeben, wird diese als Offset verwendet, limit genau wie in SQL.

$benutzer->orderby('name DESC')->limit(0, 10)->alleFinden();

WHERE-Bedingungen

gleich(string $feld, mixed $wert) / eq(string $feld, mixed $wert)

Wo field = $value

$benutzer->eq('id', 1)->find();

ungleich(string $feld, mixed $wert) / ne(string $feld, mixed $wert)

Wo field <> $value

$benutzer->ne('id', 1)->find();

isNull(string $feld)

Wo field IS NULL

$benutzer->isNull('id')->find();

isNotNull(string $feld) / notNull(string $feld)

Wo field IS NOT NULL

$benutzer->isNotNull('id')->find();

größerAls(string $feld, mixed $wert) / gt(string $feld, mixed $wert)

Wo field > $value

$benutzer->gt('id', 1)->find();

kleinerAls(string $feld, mixed $wert) / lt(string $feld, mixed $wert)

Wo field < $value

$benutzer->lt('id', 1)->find();

größerGleich(string $feld, mixed $wert) / ge(string $feld, mixed $wert) / gte(string $feld, mixed $wert)

Wo field >= $value

$benutzer->ge('id', 1)->find();

kleinerGleich(string $feld, mixed $wert) / le(string $feld, mixed $wert) / lte(string $feld, mixed $wert)

Wo field <= $value

$benutzer->le('id', 1)->find();

wie(string $feld, mixed $wert) / notLike(string $feld, mixed $wert)

Wo field LIKE $value oder field NOT LIKE $value

$benutzer->wie('name', 'de')->find();

in(string $feld, array $werte) / notIn(string $feld, array $werte)

Wo field IN($value) oder field NOT IN($value)

$benutzer->in('id', [1, 2])->find();

zwischen(string $feld, array $werte)

Wo field BETWEEN $value AND $value1

$benutzer->zwischen('id', [1, 2])->find();

Beziehungen

Sie können mehrere Arten von Beziehungen mit dieser Bibliothek festlegen. Sie können eins-zu-viele- und eins-zu-eins-Beziehungen zwischen Tabellen festlegen. Dies erfordert eine kleine zusätzliche Einrichtung in der Klasse im Voraus.

Das Einstellen des $relations-Arrays ist nicht schwierig, aber die richtige Syntax zu erraten, kann verwirrend sein.

geschütztes array $relations = [
    // Sie können den Schlüssel beliebig benennen. Der Name des ActiveRecord ist vielleicht gut. Bsp.: benutzer, kontakt, klient
    'benutzer' => [
        // erforderlich
        // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO
        self::HAS_ONE, // dies ist der Beziehungstyp

        // erforderlich
        'Einige_Klasse', // das ist die "andere" ActiveRecord-Klasse, auf die hier verwiesen wird

        // erforderlich
        // je nach Beziehungstyp
        // self::HAS_ONE = der Fremdschlüssel, der das Join referenziert
        // self::HAS_MANY = der Fremdschlüssel, der das Join referenziert
        // self::BELONGS_TO = der lokale Schlüssel, der das Join referenziert
        'lokaler_oder_fremder_schlüssel',
        // nur zur Information, das verbindet auch nur zum Primärschlüssel des "anderen" Modells

        // optional
        [ 'eq' => [ 'kunden_id', 5 ], 'auswählen' => 'COUNT(*) as anzahl', 'limit' 5 ], // zusätzliche Bedingungen, die Sie beim Zusammenfügen der Beziehung'beziehungen' => [ self::BELONGS_TO, Benutzer::class, 'benutzer_id' ],
        'benutzer_mit_backref' => [ self::BELONGS_TO, Benutzer::class, 'benutzer_id', [], 'kontakt' ],
    ];
    public function __construct($datenbankverbindung)
    {
        parent::__construct($datenbankverbindung, 'kontakte');
    }
 }

Nun sind die Verweise eingerichtet, sodass Sie sie sehr einfach verwenden können!

$benutzer = new Benutzer($pdo_verbindung);

// finde den neuesten Benutzer.
$benutzer->nichtNull('id')->orderBy('id desc')->find();

// erhalte Kontakte, indem Sie die Beziehung verwenden:
foreach($benutzer->kontakte as $kontakt) {
    echo $kontakt->id;
}

// oder wir können auch den anderen Weg gehen.
$kontakt = new Kontakt();

// finde einen Kontakt
$kontakt->find();

// erhalte den Benutzer, indem Sie die Beziehung verwenden:
echo $kontakt->benutzer->name; // dies ist der Benutzername

Ziemlich cool, oder?

Festlegung benutzerdefinierter Daten

Manchmal müssen Sie Ihrem ActiveRecord etwas Einzigartiges anhängen, wie z.B. eine benutzerdefinierte Berechnung, die möglicherweise einfacher ist, einfach dem Objekt anzuhängen, das dann an eine Vorlage übergeben werden könnte.

setBenutzerdefinierteDaten(string $feld, mixed $wert)

Sie hängen die benutzerdefinierten Daten mit der setBenutzerdefinierteDaten()-Methode an.

$benutzer->setBenutzerdefinierteDaten('seitenaufruf_anzahl', $seitenaufruf_anzahl);

Und dann verweisen Sie einfach darauf wie auf eine normale Objekteigenschaft.

echo $benutzer->seitenaufruf_anzahl;

Ereignisse

Ein weiteres wirklich tolles Feature dieser Bibliothek sind die Ereignisse. Ereignisse werden zu bestimmten Zeiten basierend auf bestimmten Methoden, die Sie aufrufen, ausgelöst. Sie sind sehr, sehr hilfreich, um Daten automatisch für Sie einzurichten.

onConstruct(ActiveRecord $ActiveRecord, array &config)

Dies ist wirklich hilfreich, wenn Sie eine Standardverbindung oder so etwas einrichten müssen.

// index.php oder bootstrap.php
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);

//
//
//

// Benutzer.php
class Benutzer extends flight\ActiveRecord {

    geschützte Funktion onConstruct(self $self, array &$config) { // vergessen Sie nicht die & Referenz
        // Sie könnten das tun, um automatisch die Verbindung einzurichten
        $config['verbindung'] = Flight::db();
        // oder das
        $self->verbindungTransformierenUndPersistieren(Flight::db());

        // Sie können den Tabellennamen auch auf diese Weise festlegen.
        $config['tabelle'] = 'benutzer';
    } 
}

vorFinden(ActiveRecord $ActiveRecord)

Das ist wahrscheinlich nur nützlich, wenn Sie eine Abfrage-Manipulation jedes Mal benötigen.

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion vorFinden(self $self) {
        // führen Sie immer id >= 0 aus, wenn das Ihr Ding ist
        $self->gte('id', 0); 
    } 
}

nachFinden(ActiveRecord $ActiveRecord)

Dies ist wahrscheinlich nützlicher, wenn Sie jedes Mal, wenn dieser Datensatz abgerufen wird, einige Logik ausführen müssen. Müssen Sie etwas entschlüsseln? Müssen Sie jedes Mal eine benutzerdefinierte Anzahlabfrage ausführen (nicht performant, aber egal)?

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion nachFinden(self $self) {
        // etwas entschlüsseln
        $self->geheimnis = ihreEntschlüsselungsfunktion($self->geheimnis, $einige_schlüssel);

        // vielleicht etwas benutzerdefiniertes wie eine Abfrage speichern???
        $self->setBenutzerdefinierteDaten('anzahl_ansichten', $self->auswählen('COUNT(*) count')->von('benutzeraufrufe')->eq('benutzer_id', $self->id)['count']; 
    } 
}

vorFindenAlles(ActiveRecord $ActiveRecord)

Dies ist wahrscheinlich nur nützlich, wenn Sie eine Abfrage-Manipulation jedes Mal benötigen.

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion vorFindenAlles(self $self) {
        // immer id >= 0 ausführen, wenn das Ihr Ding ist
        $self->gte('id', 0); 
    } 
}

nachFindenAlles(array<int,ActiveRecord> $ergebnisse)

Ähnlich wie nachFinden() können Sie dies an allen Datensätzen durchführen!

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion nachFindenAlles(array $ergebnisse) {

        Fürjeden($ergebnisse als $self) {
            // mache etwas cooles wie nachFinden()
        }
    } 
}

vorEinfügen(ActiveRecord $ActiveRecord)

Wirklich hilfreich, wenn Sie jedes Mal einige Standardwerte setzen müssen.

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion vorEinfügen(self $self) {
        // setze einige solide Standardwerte
        if(!$self->erstelltes_datum) {
            $self->erstelltes_datum = gmdate('Y-m-d');
        }

        if(!$self->passwort) {
            $self->passwort = password_hash((string) microtime(true));
        }
    } 
}

nachEinfügen(ActiveRecord $ActiveRecord)

Vielleicht hast du einen Anwendungsfall, bei dem du Daten ändern musst, nachdem sie eingefügt wurden?

class Benutzer extends flight\ActiveRecord {

    Öffentliche Funktion __konstruieren($datenbankverbindung)
    {
        parent::__konstruieren($datenbankverbindung, 'benutzer');
    }

    geschützte Funktion nachEinfügen(self $self) {
        // du machst deine Sache
        Flight::cache()->set('zuletzt_eingefügte_id', $self->id);
        // oder so weiter....

Awesome-plugins/latte

Latte

Latte ist eine voll ausgestattete Template-Engine, die sehr einfach zu bedienen ist und sich näher an einer PHP-Syntax anfühlt als Twig oder Smarty. Es ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen.

Installation

Installation mit Composer.

composer require latte/latte

Grundlegende Konfiguration

Es gibt einige grundlegende Konfigurationsoptionen, um loszulegen. Weitere Informationen dazu finden Sie in der Latte-Dokumentation.


use Latte\Engine as LatteEngine;

require 'vendor/autoload.php';

$app = Flight::app();

$app->register('latte', LatteEngine::class, [], function(LatteEngine $latte) use ($app) {

    // Hier werden Latte Ihre Templates zwischenspeichern, um die Leistung zu steigern
    // Eine coole Sache an Latte ist, dass es Ihren Cache automatisch aktualisiert,
    // wenn Sie Änderungen an Ihren Templates vornehmen!
    $latte->setTempDirectory(__DIR__ . '/../cache/');

    // Teilen Sie Latte mit, wo sich das Stammverzeichnis Ihrer Ansichten befindet.
    $latte->setLoader(new \Latte\Loaders\FileLoader($app->get('flight.views.path')));
});

Einfaches Layout-Beispiel

Hier ist ein einfaches Beispiel für eine Layout-Datei. Diese Datei wird verwendet, um alle anderen Ansichten zu umschließen.

<!-- app/views/layout.latte -->
<!doctype html>
<html lang="de">
    <head>
        <title>{$title ? $title . ' - '}Meine App</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <header>
            <nav>
                <!-- Ihre Navigations-Elemente hier -->
            </nav>
        </header>
        <div id="content">
            <!-- Hier passiert die Magie -->
            {block content}{/block}
        </div>
        <div id="footer">
            &copy; Urheberrecht
        </div>
    </body>
</html>

Und jetzt haben wir Ihre Datei, die innerhalb dieses Inhaltsblocks gerendert wird:

<!-- app/views/home.latte -->
<!-- Dies teilt Latte mit, dass diese Datei "innerhalb" der layout.latte Datei ist -->
{extends layout.latte}

<!-- Dies ist der Inhalt, der innerhalb des Layouts im Inhaltsblock gerendert wird -->
{block content}
    <h1>Startseite</h1>
    <p>Willkommen in meiner App!</p>
{/block}

Dann, wenn Sie dies in Ihrer Funktion oder Ihrem Controller rendern, würden Sie etwas Ähnliches tun:

// einfacher Route
Flight::route('/', function () {
    Flight::latte()->render('home.latte', [
        'title' => 'Startseite'
    ]);
});

// oder wenn Sie einen Controller verwenden
Flight::route('/', [HomeController::class, 'index']);

// HomeController.php
class HomeController
{
    public function index()
    {
        Flight::latte()->render('home.latte', [
            'title' => 'Startseite'
        ]);
    }
}

Besuchen Sie die Latte-Dokumentation für weitere Informationen darüber, wie Sie Latte optimal nutzen können!

Awesome-plugins/awesome_plugins

Beeindruckende Plugins

Flight ist unglaublich erweiterbar. Es gibt eine Reihe von Plugins, die verwendet werden können, um Funktionalität zu Ihrer Flight-Anwendung hinzuzufügen. Einige werden offiziell vom Flight-Team unterstützt, während andere Mikro-/Lite-Bibliotheken sind, die Ihnen helfen, loszulegen.

Zwischenspeicherung

Das Zwischenspeichern ist ein großartiger Weg, um Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Zwischenspeicherungsbibliotheken, die mit Flight verwendet werden können.

Cookies

Cookies sind eine großartige Möglichkeit, um kleine Datenstücke auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzereinstellungen, Anwendungseinstellungen und mehr zu speichern.

Debuggen

Debuggen ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt einige Plugins, die Ihr Debug-Erlebnis verbessern können.

Datenbanken

Datenbanken sind das Herzstück vieler Anwendungen. So speichern und abrufen Sie Daten. Einige Datenbankbibliotheken sind einfach Wrapper, um Abfragen zu schreiben, während andere umfassende ORMs sind.

Verschlüsselung

Verschlüsselung ist für jede Anwendung, die sensible Daten speichert, entscheidend. Das Verschlüsseln und Entschlüsseln der Daten ist nicht besonders schwierig, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels kann schwierig sein. Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu übernehmen.

Sitzung

Sitzungen sind für APIs nicht wirklich nützlich, aber für den Aufbau einer Webanwendung können Sitzungen entscheidend sein, um den Zustand und die Anmeldeinformationen aufrechtzuerhalten.

Vorlagen

Vorlagen sind wesentlich für jede Webanwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Vorlagen-Engines, die mit Flight verwendet werden können.

Mitwirken

Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie einen Pull-Request ein, um es der Liste hinzuzufügen!

Examples

Brauchen Sie einen schnellen Einstieg?

Besuchen Sie das flightphp/skeleton Repository, um loszulegen! Dies ist ein Projekt, das eine einzelne Datei enthält, die alles enthält, was Sie benötigen, um Ihre App auszuführen. Es enthält auch ein umfangreicheres Beispiel mit Controllern und Views.

Brauchen Sie etwas Inspiration?

Obwohl diese nicht offiziell vom Flight Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen Projekte strukturieren können, die mit Flight erstellt wurden!

Möchten Sie Ihr eigenes Beispiel teilen?

Wenn Sie ein Projekt haben, das Sie teilen möchten, reichen Sie bitte einen Pull-Request ein, um es zu dieser Liste hinzuzufügen!